github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/misc/cgo/testsigfwd/main.go (about) 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 exit(0); // success 29 } 30 } 31 32 static volatile sig_atomic_t sigioSeen; 33 34 // Use up some stack space. 35 static void recur(int i, char *p) { 36 char a[1024]; 37 38 *p = '\0'; 39 if (i > 0) { 40 recur(i - 1, a); 41 } 42 } 43 44 static void iohandler(int signum) { 45 char a[1024]; 46 47 recur(4, a); 48 sigioSeen = 1; 49 } 50 51 static void* sigioThread(void* arg __attribute__ ((unused))) { 52 raise(SIGIO); 53 } 54 55 static void sigioOnThread() { 56 pthread_t tid; 57 int i; 58 59 pthread_create(&tid, NULL, sigioThread, NULL); 60 pthread_join(tid, NULL); 61 62 // Wait until the signal has been delivered. 63 i = 0; 64 while (!sigioSeen) { 65 if (sched_yield() < 0) { 66 perror("sched_yield"); 67 } 68 i++; 69 if (i > 10000) { 70 fprintf(stderr, "looping too long waiting for signal\n"); 71 exit(EXIT_FAILURE); 72 } 73 } 74 } 75 76 static void __attribute__ ((constructor)) sigsetup(void) { 77 struct sigaction act; 78 79 memset(&act, 0, sizeof act); 80 act.sa_handler = segvhandler; 81 sigaction(SIGSEGV, &act, NULL); 82 83 act.sa_handler = iohandler; 84 sigaction(SIGIO, &act, NULL); 85 } 86 */ 87 import "C" 88 89 var p *byte 90 91 func f() (ret bool) { 92 defer func() { 93 if recover() == nil { 94 fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.") 95 C.exit(2) 96 } 97 ret = true 98 }() 99 *p = 1 100 return false 101 } 102 103 func main() { 104 // Test that the signal originating in Go is handled (and recovered) by Go. 105 if !f() { 106 fmt.Errorf("couldn't recover from SIGSEGV in Go.") 107 C.exit(2) 108 } 109 110 // Test that the signal originating in C is handled by C. 111 C.sigsegv() 112 }