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 return NULL; 54 } 55 56 static void sigioOnThread() { 57 pthread_t tid; 58 int i; 59 60 pthread_create(&tid, NULL, sigioThread, NULL); 61 pthread_join(tid, NULL); 62 63 // Wait until the signal has been delivered. 64 i = 0; 65 while (!sigioSeen) { 66 if (sched_yield() < 0) { 67 perror("sched_yield"); 68 } 69 i++; 70 if (i > 10000) { 71 fprintf(stderr, "looping too long waiting for signal\n"); 72 exit(EXIT_FAILURE); 73 } 74 } 75 } 76 77 static void __attribute__ ((constructor)) sigsetup(void) { 78 struct sigaction act; 79 80 memset(&act, 0, sizeof act); 81 act.sa_handler = segvhandler; 82 sigaction(SIGSEGV, &act, NULL); 83 84 act.sa_handler = iohandler; 85 sigaction(SIGIO, &act, NULL); 86 } 87 */ 88 import "C" 89 90 var p *byte 91 92 func f() (ret bool) { 93 defer func() { 94 if recover() == nil { 95 fmt.Errorf("ERROR: couldn't raise SIGSEGV in Go.") 96 C.exit(2) 97 } 98 ret = true 99 }() 100 *p = 1 101 return false 102 } 103 104 func main() { 105 // Test that the signal originating in Go is handled (and recovered) by Go. 106 if !f() { 107 fmt.Errorf("couldn't recover from SIGSEGV in Go.") 108 C.exit(2) 109 } 110 111 // Test that the signal originating in C is handled by C. 112 C.sigsegv() 113 } 114