Source file misc/cgo/testsigfwd/main.go
1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import "fmt" 8 9 /* 10 #cgo CFLAGS: -pthread 11 #cgo LDFLAGS: -pthread 12 13 #include <signal.h> 14 #include <stdlib.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <pthread.h> 18 19 int *p; 20 static void sigsegv() { 21 *p = 1; 22 fprintf(stderr, "ERROR: C SIGSEGV not thrown on caught?.\n"); 23 exit(2); 24 } 25 26 static void segvhandler(int signum) { 27 if (signum == SIGSEGV) { 28 fprintf(stdout, "ok\ttestsigfwd\n"); 29 exit(0); // success 30 } 31 } 32 33 static volatile sig_atomic_t sigioSeen; 34 35 // Use up some stack space. 36 static void recur(int i, char *p) { 37 char a[1024]; 38 39 *p = '\0'; 40 if (i > 0) { 41 recur(i - 1, a); 42 } 43 } 44 45 static void iohandler(int signum) { 46 char a[1024]; 47 48 recur(4, a); 49 sigioSeen = 1; 50 } 51 52 static void* sigioThread(void* arg __attribute__ ((unused))) { 53 raise(SIGIO); 54 return NULL; 55 } 56 57 static void sigioOnThread() { 58 pthread_t tid; 59 int i; 60 61 pthread_create(&tid, NULL, sigioThread, NULL); 62 pthread_join(tid, NULL); 63 64 // Wait until the signal has been delivered. 65 i = 0; 66 while (!sigioSeen) { 67 if (sched_yield() < 0) { 68 perror("sched_yield"); 69 } 70 i++; 71 if (i > 10000) { 72 fprintf(stderr, "looping too long waiting for signal\n"); 73 exit(EXIT_FAILURE); 74 } 75 } 76 } 77 78 static void __attribute__ ((constructor)) sigsetup(void) { 79 struct sigaction act; 80 81 memset(&act, 0, sizeof act); 82 act.sa_handler = segvhandler; 83 sigaction(SIGSEGV, &act, NULL); 84 85 act.sa_handler = iohandler; 86 sigaction(SIGIO, &act, NULL); 87 } 88 */ 89 import "C" 90 91 var p *byte 92 93 func f() (ret bool) { 94 defer func() { 95 if recover() == nil { 96 fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.") 97 C.exit(2) 98 } 99 ret = true 100 }() 101 *p = 1 102 return false 103 } 104 105 func main() { 106 // Test that the signal originating in Go is handled (and recovered) by Go. 107 if !f() { 108 fmt.Errorf("couldn't recover from SIGSEGV in Go.") 109 C.exit(2) 110 } 111 112 // Test that the signal originating in C is handled by C. 113 C.sigsegv() 114 } 115