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.
5 // Test installing a signal handler before the Go code starts.
6 // This is a lot like misc/cgo/testcshared/main4.c.
16 #include <sys/types.h>
24 static void die(const char* msg) {
29 static volatile sig_atomic_t sigioSeen;
30 static volatile sig_atomic_t sigpipeSeen;
32 // Use up some stack space.
33 static void recur(int i, char *p) {
42 static void pipeHandler(int signo, siginfo_t* info, void* ctxt) {
46 // Signal handler that uses up more stack space than a goroutine will have.
47 static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
55 static char* nullPointer;
57 // An arbitrary function which requires proper stack alignment; see
58 // http://golang.org/issue/17641.
59 static void callWithVarargs(void* dummy, ...) {
61 va_start(args, dummy);
65 // Signal handler for SIGSEGV on a C thread.
66 static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
70 // Call an arbitrary function that requires the stack to be properly aligned.
71 callWithVarargs("dummy arg", 3.1415);
73 if (sigemptyset(&mask) < 0) {
76 if (sigaddset(&mask, SIGSEGV) < 0) {
79 i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
81 fprintf(stderr, "sigprocmask: %s\n", strerror(i));
85 // Don't try this at home.
88 // We should never get here.
92 // Set up the signal handlers in a high priority constructor,
93 // so that they are installed before the Go code starts.
95 static void init(void) __attribute__ ((constructor (200)));
100 memset(&sa, 0, sizeof sa);
101 sa.sa_sigaction = ioHandler;
102 if (sigemptyset(&sa.sa_mask) < 0) {
105 sa.sa_flags = SA_SIGINFO;
106 if (sigaction(SIGIO, &sa, NULL) < 0) {
110 sa.sa_sigaction = segvHandler;
111 if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
115 sa.sa_sigaction = pipeHandler;
116 if (sigaction(SIGPIPE, &sa, NULL) < 0) {
121 int main(int argc, char** argv) {
128 darwin = atoi(argv[1]);
132 setvbuf(stdout, NULL, _IONBF, 0);
134 // Call setsid so that we can use kill(0, SIGIO) below.
135 // Don't check the return value so that this works both from
136 // a job control shell and from a shell script.
140 printf("calling RunGoroutines\n");
145 // Block SIGIO in this thread to make it more likely that it
146 // will be delivered to a goroutine.
149 printf("calling pthread_sigmask\n");
152 if (sigemptyset(&mask) < 0) {
155 if (sigaddset(&mask, SIGIO) < 0) {
158 i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
160 fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
165 printf("calling kill\n");
168 if (kill(0, SIGIO) < 0) {
173 printf("waiting for sigioSeen\n");
176 // Wait until the signal has been delivered.
180 ts.tv_nsec = 1000000;
181 nanosleep(&ts, NULL);
184 fprintf(stderr, "looping too long waiting for SIGIO\n");
190 printf("provoking SIGPIPE\n");
193 // SIGPIPE is never forwarded on Darwin, see golang.org/issue/33384.
198 printf("waiting for sigpipeSeen\n");
201 // Wait until the signal has been delivered.
203 while (!sigpipeSeen) {
205 ts.tv_nsec = 1000000;
206 nanosleep(&ts, NULL);
209 fprintf(stderr, "looping too long waiting for SIGPIPE\n");
216 printf("calling setjmp\n");
219 // Test that a SIGSEGV on this thread is delivered to us.
220 if (setjmp(jmp) == 0) {
222 printf("triggering SIGSEGV\n");
227 fprintf(stderr, "continued after address error\n");
232 printf("calling TestSEGV\n");