/cp
[official-gcc.git] / libgo / runtime / go-signal.c
blob1624122dace8c193a697c33b6a08ecb07f4cd1aa
1 /* go-signal.c -- signal handling for Go.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/time.h>
12 #include "runtime.h"
13 #include "go-assert.h"
14 #include "go-panic.h"
15 #include "signal_unix.h"
17 #ifndef SA_RESTART
18 #define SA_RESTART 0
19 #endif
21 #ifdef USING_SPLIT_STACK
23 extern void __splitstack_getcontext(void *context[10]);
25 extern void __splitstack_setcontext(void *context[10]);
27 #endif
29 #define N SigNotify
30 #define K SigKill
31 #define T SigThrow
32 #define P SigPanic
33 #define D SigDefault
35 /* Signal actions. This collects the sigtab tables for several
36 different targets from the master library. SIGKILL, SIGCONT, and
37 SIGSTOP are not listed, as we don't want to set signal handlers for
38 them. */
40 SigTab runtime_sigtab[] = {
41 #ifdef SIGHUP
42 { SIGHUP, N + K },
43 #endif
44 #ifdef SIGINT
45 { SIGINT, N + K },
46 #endif
47 #ifdef SIGQUIT
48 { SIGQUIT, N + T },
49 #endif
50 #ifdef SIGILL
51 { SIGILL, T },
52 #endif
53 #ifdef SIGTRAP
54 { SIGTRAP, T },
55 #endif
56 #ifdef SIGABRT
57 { SIGABRT, N + T },
58 #endif
59 #ifdef SIGBUS
60 { SIGBUS, P },
61 #endif
62 #ifdef SIGFPE
63 { SIGFPE, P },
64 #endif
65 #ifdef SIGUSR1
66 { SIGUSR1, N },
67 #endif
68 #ifdef SIGSEGV
69 { SIGSEGV, P },
70 #endif
71 #ifdef SIGUSR2
72 { SIGUSR2, N },
73 #endif
74 #ifdef SIGPIPE
75 { SIGPIPE, N },
76 #endif
77 #ifdef SIGALRM
78 { SIGALRM, N },
79 #endif
80 #ifdef SIGTERM
81 { SIGTERM, N + K },
82 #endif
83 #ifdef SIGSTKFLT
84 { SIGSTKFLT, T },
85 #endif
86 #ifdef SIGCHLD
87 { SIGCHLD, N },
88 #endif
89 #ifdef SIGTSTP
90 { SIGTSTP, N + D },
91 #endif
92 #ifdef SIGTTIN
93 { SIGTTIN, N + D },
94 #endif
95 #ifdef SIGTTOU
96 { SIGTTOU, N + D },
97 #endif
98 #ifdef SIGURG
99 { SIGURG, N },
100 #endif
101 #ifdef SIGXCPU
102 { SIGXCPU, N },
103 #endif
104 #ifdef SIGXFSZ
105 { SIGXFSZ, N },
106 #endif
107 #ifdef SIGVTALRM
108 { SIGVTALRM, N },
109 #endif
110 #ifdef SIGPROF
111 { SIGPROF, N },
112 #endif
113 #ifdef SIGWINCH
114 { SIGWINCH, N },
115 #endif
116 #ifdef SIGIO
117 { SIGIO, N },
118 #endif
119 #ifdef SIGPWR
120 { SIGPWR, N },
121 #endif
122 #ifdef SIGSYS
123 { SIGSYS, N },
124 #endif
125 #ifdef SIGEMT
126 { SIGEMT, T },
127 #endif
128 #ifdef SIGINFO
129 { SIGINFO, N },
130 #endif
131 #ifdef SIGTHR
132 { SIGTHR, N },
133 #endif
134 { -1, 0 }
136 #undef N
137 #undef K
138 #undef T
139 #undef P
140 #undef D
142 /* Handle a signal, for cases where we don't panic. We can split the
143 stack here. */
145 void
146 runtime_sighandler (int sig, Siginfo *info,
147 void *context __attribute__ ((unused)), G *gp)
149 M *m;
150 int i;
152 m = runtime_m ();
154 #ifdef SIGPROF
155 if (sig == SIGPROF)
157 if (m != NULL && gp != m->g0 && gp != m->gsignal)
158 runtime_sigprof ();
159 return;
161 #endif
163 if (m == NULL)
165 runtime_badsignal (sig);
166 return;
169 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
171 SigTab *t;
172 bool notify, crash;
174 t = &runtime_sigtab[i];
176 if (t->sig != sig)
177 continue;
179 notify = false;
180 #ifdef SA_SIGINFO
181 notify = info != NULL && info->si_code == SI_USER;
182 #endif
183 if (notify || (t->flags & SigNotify) != 0)
185 if (__go_sigsend (sig))
186 return;
188 if ((t->flags & SigKill) != 0)
189 runtime_exit (2);
190 if ((t->flags & SigThrow) == 0)
191 return;
193 runtime_startpanic ();
196 const char *name = NULL;
198 #ifdef HAVE_STRSIGNAL
199 name = strsignal (sig);
200 #endif
202 if (name == NULL)
203 runtime_printf ("Signal %d\n", sig);
204 else
205 runtime_printf ("%s\n", name);
208 if (m->lockedg != NULL && m->ncgo > 0 && gp == m->g0)
210 runtime_printf("signal arrived during cgo execution\n");
211 gp = m->lockedg;
214 runtime_printf ("\n");
216 if (runtime_gotraceback (&crash))
218 G *g;
220 g = runtime_g ();
221 runtime_traceback ();
222 runtime_tracebackothers (g);
224 /* The gc library calls runtime_dumpregs here, and provides
225 a function that prints the registers saved in context in
226 a readable form. */
229 if (crash)
230 runtime_crash ();
232 runtime_exit (2);
235 __builtin_unreachable ();
238 /* The start of handling a signal which panics. */
240 static void
241 sig_panic_leadin (int sig)
243 int i;
244 sigset_t clear;
246 if (runtime_m ()->mallocing)
248 runtime_printf ("caught signal while mallocing: %d\n", sig);
249 runtime_throw ("caught signal while mallocing");
252 /* The signal handler blocked signals; unblock them. */
253 i = sigfillset (&clear);
254 __go_assert (i == 0);
255 i = pthread_sigmask (SIG_UNBLOCK, &clear, NULL);
256 __go_assert (i == 0);
259 #ifdef SA_SIGINFO
261 /* Signal dispatch for signals which panic, on systems which support
262 SA_SIGINFO. This is called on the thread stack, and as such it is
263 permitted to split the stack. */
265 static void
266 sig_panic_info_handler (int sig, Siginfo *info, void *context)
268 G *g;
270 g = runtime_g ();
271 if (g == NULL || info->si_code == SI_USER)
273 runtime_sighandler (sig, info, context, g);
274 return;
277 g->sig = sig;
278 g->sigcode0 = info->si_code;
279 g->sigcode1 = (uintptr_t) info->si_addr;
281 /* It would be nice to set g->sigpc here as the gc library does, but
282 I don't know how to get it portably. */
284 sig_panic_leadin (sig);
286 switch (sig)
288 #ifdef SIGBUS
289 case SIGBUS:
290 if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
291 runtime_panicstring ("invalid memory address or "
292 "nil pointer dereference");
293 runtime_printf ("unexpected fault address %p\n", info->si_addr);
294 runtime_throw ("fault");
295 #endif
297 #ifdef SIGSEGV
298 case SIGSEGV:
299 if ((info->si_code == 0
300 || info->si_code == SEGV_MAPERR
301 || info->si_code == SEGV_ACCERR)
302 && (uintptr_t) info->si_addr < 0x1000)
303 runtime_panicstring ("invalid memory address or "
304 "nil pointer dereference");
305 runtime_printf ("unexpected fault address %p\n", info->si_addr);
306 runtime_throw ("fault");
307 #endif
309 #ifdef SIGFPE
310 case SIGFPE:
311 switch (info->si_code)
313 case FPE_INTDIV:
314 runtime_panicstring ("integer divide by zero");
315 case FPE_INTOVF:
316 runtime_panicstring ("integer overflow");
318 runtime_panicstring ("floating point error");
319 #endif
322 /* All signals with SigPanic should be in cases above, and this
323 handler should only be invoked for those signals. */
324 __builtin_unreachable ();
327 #else /* !defined (SA_SIGINFO) */
329 static void
330 sig_panic_handler (int sig)
332 G *g;
334 g = runtime_g ();
335 if (g == NULL)
337 runtime_sighandler (sig, NULL, NULL, g);
338 return;
341 g->sig = sig;
342 g->sigcode0 = 0;
343 g->sigcode1 = 0;
345 sig_panic_leadin (sig);
347 switch (sig)
349 #ifdef SIGBUS
350 case SIGBUS:
351 runtime_panicstring ("invalid memory address or "
352 "nil pointer dereference");
353 #endif
355 #ifdef SIGSEGV
356 case SIGSEGV:
357 runtime_panicstring ("invalid memory address or "
358 "nil pointer dereference");
359 #endif
361 #ifdef SIGFPE
362 case SIGFPE:
363 runtime_panicstring ("integer divide by zero or floating point error");
364 #endif
367 /* All signals with SigPanic should be in cases above, and this
368 handler should only be invoked for those signals. */
369 __builtin_unreachable ();
372 #endif /* !defined (SA_SIGINFO) */
374 /* A signal handler used for signals which are not going to panic.
375 This is called on the alternate signal stack so it may not split
376 the stack. */
378 static void
379 sig_tramp_info (int, Siginfo *, void *) __attribute__ ((no_split_stack));
381 static void
382 sig_tramp_info (int sig, Siginfo *info, void *context)
384 G *gp;
385 M *mp;
386 #ifdef USING_SPLIT_STACK
387 void *stack_context[10];
388 #endif
390 /* We are now running on the stack registered via sigaltstack.
391 (Actually there is a small span of time between runtime_siginit
392 and sigaltstack when the program starts.) */
393 gp = runtime_g ();
394 mp = runtime_m ();
396 if (gp != NULL)
398 #ifdef USING_SPLIT_STACK
399 __splitstack_getcontext (&stack_context[0]);
400 #endif
403 if (gp != NULL && mp->gsignal != NULL)
405 /* We are running on the signal stack. Set the split stack
406 context so that the stack guards are checked correctly. */
407 #ifdef USING_SPLIT_STACK
408 __splitstack_setcontext (&mp->gsignal->stack_context[0]);
409 #endif
412 runtime_sighandler (sig, info, context, gp);
414 /* We are going to return back to the signal trampoline and then to
415 whatever we were doing before we got the signal. Restore the
416 split stack context so that stack guards are checked
417 correctly. */
419 if (gp != NULL)
421 #ifdef USING_SPLIT_STACK
422 __splitstack_setcontext (&stack_context[0]);
423 #endif
427 #ifndef SA_SIGINFO
429 static void sig_tramp (int sig) __attribute__ ((no_split_stack));
431 static void
432 sig_tramp (int sig)
434 sig_tramp_info (sig, NULL, NULL);
437 #endif
439 void
440 runtime_setsig (int32 i, GoSighandler *fn, bool restart)
442 struct sigaction sa;
443 int r;
444 SigTab *t;
446 memset (&sa, 0, sizeof sa);
448 r = sigfillset (&sa.sa_mask);
449 __go_assert (r == 0);
451 t = &runtime_sigtab[i];
453 if ((t->flags & SigPanic) == 0)
455 #ifdef SA_SIGINFO
456 sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
457 if (fn == runtime_sighandler)
458 fn = (void *) sig_tramp_info;
459 sa.sa_sigaction = (void *) fn;
460 #else
461 sa.sa_flags = SA_ONSTACK;
462 if (fn == runtime_sighandler)
463 fn = (void *) sig_tramp;
464 sa.sa_handler = (void *) fn;
465 #endif
467 else
469 #ifdef SA_SIGINFO
470 sa.sa_flags = SA_SIGINFO;
471 if (fn == runtime_sighandler)
472 fn = (void *) sig_panic_info_handler;
473 sa.sa_sigaction = (void *) fn;
474 #else
475 sa.sa_flags = 0;
476 if (fn == runtime_sighandler)
477 fn = (void *) sig_panic_handler;
478 sa.sa_handler = (void *) fn;
479 #endif
482 if (restart)
483 sa.sa_flags |= SA_RESTART;
485 if (sigaction (t->sig, &sa, NULL) != 0)
486 __go_assert (0);
489 GoSighandler*
490 runtime_getsig (int32 i)
492 struct sigaction sa;
493 int r;
494 SigTab *t;
496 memset (&sa, 0, sizeof sa);
498 r = sigemptyset (&sa.sa_mask);
499 __go_assert (r == 0);
501 t = &runtime_sigtab[i];
503 if (sigaction (t->sig, NULL, &sa) != 0)
504 runtime_throw ("sigaction read failure");
506 if ((void *) sa.sa_handler == sig_tramp_info)
507 return runtime_sighandler;
508 #ifdef SA_SIGINFO
509 if ((void *) sa.sa_handler == sig_panic_info_handler)
510 return runtime_sighandler;
511 #else
512 if ((void *) sa.sa_handler == sig_tramp
513 || (void *) sa.sa_handler == sig_panic_handler)
514 return runtime_sighandler;
515 #endif
517 return (void *) sa.sa_handler;
520 /* Used by the os package to raise SIGPIPE. */
522 void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe");
524 void
525 os_sigpipe (void)
527 struct sigaction sa;
528 int i;
530 memset (&sa, 0, sizeof sa);
532 sa.sa_handler = SIG_DFL;
534 i = sigemptyset (&sa.sa_mask);
535 __go_assert (i == 0);
537 if (sigaction (SIGPIPE, &sa, NULL) != 0)
538 abort ();
540 raise (SIGPIPE);
543 void
544 runtime_setprof(bool on)
546 USED(on);