1 /* go-signal.c -- signal handling for Go.
2
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. */
6
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/time.h>
11
12 #include "runtime.h"
13 #include "go-assert.h"
14 #include "go-panic.h"
15 #include "signal_unix.h"
16
17 #ifndef SA_RESTART
18 #define SA_RESTART 0
19 #endif
20
21 #ifdef USING_SPLIT_STACK
22
23 extern void __splitstack_getcontext(void *context[10]);
24
25 extern void __splitstack_setcontext(void *context[10]);
26
27 #endif
28
29 #define N SigNotify
30 #define K SigKill
31 #define T SigThrow
32 #define P SigPanic
33 #define D SigDefault
34
35 /* Signal actions. This collects the sigtab tables for several
36 different targets from the master library. SIGKILL and SIGSTOP are
37 not listed, as we don't want to set signal handlers for them. */
38
39 SigTab runtime_sigtab[] = {
40 #ifdef SIGHUP
41 { SIGHUP, N + K, NULL },
42 #endif
43 #ifdef SIGINT
44 { SIGINT, N + K, NULL },
45 #endif
46 #ifdef SIGQUIT
47 { SIGQUIT, N + T, NULL },
48 #endif
49 #ifdef SIGILL
50 { SIGILL, T, NULL },
51 #endif
52 #ifdef SIGTRAP
53 { SIGTRAP, T, NULL },
54 #endif
55 #ifdef SIGABRT
56 { SIGABRT, N + T, NULL },
57 #endif
58 #ifdef SIGBUS
59 { SIGBUS, P, NULL },
60 #endif
61 #ifdef SIGFPE
62 { SIGFPE, P, NULL },
63 #endif
64 #ifdef SIGUSR1
65 { SIGUSR1, N, NULL },
66 #endif
67 #ifdef SIGSEGV
68 { SIGSEGV, P, NULL },
69 #endif
70 #ifdef SIGUSR2
71 { SIGUSR2, N, NULL },
72 #endif
73 #ifdef SIGPIPE
74 { SIGPIPE, N, NULL },
75 #endif
76 #ifdef SIGALRM
77 { SIGALRM, N, NULL },
78 #endif
79 #ifdef SIGTERM
80 { SIGTERM, N + K, NULL },
81 #endif
82 #ifdef SIGSTKFLT
83 { SIGSTKFLT, T, NULL },
84 #endif
85 #ifdef SIGCHLD
86 { SIGCHLD, N, NULL },
87 #endif
88 #ifdef SIGCONT
89 { SIGCONT, N + D, NULL },
90 #endif
91 #ifdef SIGTSTP
92 { SIGTSTP, N + D, NULL },
93 #endif
94 #ifdef SIGTTIN
95 { SIGTTIN, N + D, NULL },
96 #endif
97 #ifdef SIGTTOU
98 { SIGTTOU, N + D, NULL },
99 #endif
100 #ifdef SIGURG
101 { SIGURG, N, NULL },
102 #endif
103 #ifdef SIGXCPU
104 { SIGXCPU, N, NULL },
105 #endif
106 #ifdef SIGXFSZ
107 { SIGXFSZ, N, NULL },
108 #endif
109 #ifdef SIGVTALRM
110 { SIGVTALRM, N, NULL },
111 #endif
112 #ifdef SIGPROF
113 { SIGPROF, N, NULL },
114 #endif
115 #ifdef SIGWINCH
116 { SIGWINCH, N, NULL },
117 #endif
118 #ifdef SIGIO
119 { SIGIO, N, NULL },
120 #endif
121 #ifdef SIGPWR
122 { SIGPWR, N, NULL },
123 #endif
124 #ifdef SIGSYS
125 { SIGSYS, N, NULL },
126 #endif
127 #ifdef SIGEMT
128 { SIGEMT, T, NULL },
129 #endif
130 #ifdef SIGINFO
131 { SIGINFO, N, NULL },
132 #endif
133 #ifdef SIGTHR
134 { SIGTHR, N, NULL },
135 #endif
136 { -1, 0, NULL }
137 };
138 #undef N
139 #undef K
140 #undef T
141 #undef P
142 #undef D
143
144 /* Handle a signal, for cases where we don't panic. We can split the
145 stack here. */
146
147 void
runtime_sighandler(int sig,Siginfo * info,void * context,G * gp)148 runtime_sighandler (int sig, Siginfo *info,
149 void *context __attribute__ ((unused)), G *gp)
150 {
151 M *m;
152 int i;
153
154 m = runtime_m ();
155
156 #ifdef SIGPROF
157 if (sig == SIGPROF)
158 {
159 if (m != NULL && gp != m->g0 && gp != m->gsignal)
160 runtime_sigprof ();
161 return;
162 }
163 #endif
164
165 if (m == NULL)
166 {
167 runtime_badsignal (sig);
168 return;
169 }
170
171 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
172 {
173 SigTab *t;
174 bool notify, crash;
175
176 t = &runtime_sigtab[i];
177
178 if (t->sig != sig)
179 continue;
180
181 notify = false;
182 #ifdef SA_SIGINFO
183 notify = info != NULL && info->si_code == SI_USER;
184 #endif
185 if (notify || (t->flags & SigNotify) != 0)
186 {
187 if (__go_sigsend (sig))
188 return;
189 }
190 if ((t->flags & SigKill) != 0)
191 runtime_exit (2);
192 if ((t->flags & SigThrow) == 0)
193 return;
194
195 runtime_startpanic ();
196
197 {
198 const char *name = NULL;
199
200 #ifdef HAVE_STRSIGNAL
201 name = strsignal (sig);
202 #endif
203
204 if (name == NULL)
205 runtime_printf ("Signal %d\n", sig);
206 else
207 runtime_printf ("%s\n", name);
208 }
209
210 if (m->lockedg != NULL && m->ncgo > 0 && gp == m->g0)
211 {
212 runtime_printf("signal arrived during cgo execution\n");
213 gp = m->lockedg;
214 }
215
216 runtime_printf ("\n");
217
218 if (runtime_gotraceback (&crash))
219 {
220 G *g;
221
222 g = runtime_g ();
223 runtime_traceback ();
224 runtime_tracebackothers (g);
225
226 /* The gc library calls runtime_dumpregs here, and provides
227 a function that prints the registers saved in context in
228 a readable form. */
229 }
230
231 if (crash)
232 runtime_crash ();
233
234 runtime_exit (2);
235 }
236
237 __builtin_unreachable ();
238 }
239
240 /* The start of handling a signal which panics. */
241
242 static void
sig_panic_leadin(G * gp)243 sig_panic_leadin (G *gp)
244 {
245 int i;
246 sigset_t clear;
247
248 if (!runtime_canpanic (gp))
249 runtime_throw ("unexpected signal during runtime execution");
250
251 /* The signal handler blocked signals; unblock them. */
252 i = sigfillset (&clear);
253 __go_assert (i == 0);
254 i = pthread_sigmask (SIG_UNBLOCK, &clear, NULL);
255 __go_assert (i == 0);
256 }
257
258 #ifdef SA_SIGINFO
259
260 /* Signal dispatch for signals which panic, on systems which support
261 SA_SIGINFO. This is called on the thread stack, and as such it is
262 permitted to split the stack. */
263
264 static void
sig_panic_info_handler(int sig,Siginfo * info,void * context)265 sig_panic_info_handler (int sig, Siginfo *info, void *context)
266 {
267 G *g;
268
269 g = runtime_g ();
270 if (g == NULL || info->si_code == SI_USER)
271 {
272 runtime_sighandler (sig, info, context, g);
273 return;
274 }
275
276 g->sig = sig;
277 g->sigcode0 = info->si_code;
278 g->sigcode1 = (uintptr_t) info->si_addr;
279
280 /* It would be nice to set g->sigpc here as the gc library does, but
281 I don't know how to get it portably. */
282
283 sig_panic_leadin (g);
284
285 switch (sig)
286 {
287 #ifdef SIGBUS
288 case SIGBUS:
289 if ((info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
290 || g->paniconfault)
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
296
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 || g->paniconfault)
304 runtime_panicstring ("invalid memory address or "
305 "nil pointer dereference");
306 runtime_printf ("unexpected fault address %p\n", info->si_addr);
307 runtime_throw ("fault");
308 #endif
309
310 #ifdef SIGFPE
311 case SIGFPE:
312 switch (info->si_code)
313 {
314 case FPE_INTDIV:
315 runtime_panicstring ("integer divide by zero");
316 case FPE_INTOVF:
317 runtime_panicstring ("integer overflow");
318 }
319 runtime_panicstring ("floating point error");
320 #endif
321 }
322
323 /* All signals with SigPanic should be in cases above, and this
324 handler should only be invoked for those signals. */
325 __builtin_unreachable ();
326 }
327
328 #else /* !defined (SA_SIGINFO) */
329
330 static void
sig_panic_handler(int sig)331 sig_panic_handler (int sig)
332 {
333 G *g;
334
335 g = runtime_g ();
336 if (g == NULL)
337 {
338 runtime_sighandler (sig, NULL, NULL, g);
339 return;
340 }
341
342 g->sig = sig;
343 g->sigcode0 = 0;
344 g->sigcode1 = 0;
345
346 sig_panic_leadin (g);
347
348 switch (sig)
349 {
350 #ifdef SIGBUS
351 case SIGBUS:
352 runtime_panicstring ("invalid memory address or "
353 "nil pointer dereference");
354 #endif
355
356 #ifdef SIGSEGV
357 case SIGSEGV:
358 runtime_panicstring ("invalid memory address or "
359 "nil pointer dereference");
360 #endif
361
362 #ifdef SIGFPE
363 case SIGFPE:
364 runtime_panicstring ("integer divide by zero or floating point error");
365 #endif
366 }
367
368 /* All signals with SigPanic should be in cases above, and this
369 handler should only be invoked for those signals. */
370 __builtin_unreachable ();
371 }
372
373 #endif /* !defined (SA_SIGINFO) */
374
375 /* A signal handler used for signals which are not going to panic.
376 This is called on the alternate signal stack so it may not split
377 the stack. */
378
379 static void
380 sig_tramp_info (int, Siginfo *, void *) __attribute__ ((no_split_stack));
381
382 static void
sig_tramp_info(int sig,Siginfo * info,void * context)383 sig_tramp_info (int sig, Siginfo *info, void *context)
384 {
385 G *gp;
386 M *mp;
387 #ifdef USING_SPLIT_STACK
388 void *stack_context[10];
389 #endif
390
391 /* We are now running on the stack registered via sigaltstack.
392 (Actually there is a small span of time between runtime_siginit
393 and sigaltstack when the program starts.) */
394 gp = runtime_g ();
395 mp = runtime_m ();
396
397 if (gp != NULL)
398 {
399 #ifdef USING_SPLIT_STACK
400 __splitstack_getcontext (&stack_context[0]);
401 #endif
402 }
403
404 if (gp != NULL && mp->gsignal != NULL)
405 {
406 /* We are running on the signal stack. Set the split stack
407 context so that the stack guards are checked correctly. */
408 #ifdef USING_SPLIT_STACK
409 __splitstack_setcontext (&mp->gsignal->stack_context[0]);
410 #endif
411 }
412
413 runtime_sighandler (sig, info, context, gp);
414
415 /* We are going to return back to the signal trampoline and then to
416 whatever we were doing before we got the signal. Restore the
417 split stack context so that stack guards are checked
418 correctly. */
419
420 if (gp != NULL)
421 {
422 #ifdef USING_SPLIT_STACK
423 __splitstack_setcontext (&stack_context[0]);
424 #endif
425 }
426 }
427
428 #ifndef SA_SIGINFO
429
430 static void sig_tramp (int sig) __attribute__ ((no_split_stack));
431
432 static void
sig_tramp(int sig)433 sig_tramp (int sig)
434 {
435 sig_tramp_info (sig, NULL, NULL);
436 }
437
438 #endif
439
440 void
runtime_setsig(int32 i,GoSighandler * fn,bool restart)441 runtime_setsig (int32 i, GoSighandler *fn, bool restart)
442 {
443 struct sigaction sa;
444 int r;
445 SigTab *t;
446
447 memset (&sa, 0, sizeof sa);
448
449 r = sigfillset (&sa.sa_mask);
450 __go_assert (r == 0);
451
452 t = &runtime_sigtab[i];
453
454 if ((t->flags & SigPanic) == 0)
455 {
456 #ifdef SA_SIGINFO
457 sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
458 if (fn == runtime_sighandler)
459 fn = (void *) sig_tramp_info;
460 sa.sa_sigaction = (void *) fn;
461 #else
462 sa.sa_flags = SA_ONSTACK;
463 if (fn == runtime_sighandler)
464 fn = (void *) sig_tramp;
465 sa.sa_handler = (void *) fn;
466 #endif
467 }
468 else
469 {
470 #ifdef SA_SIGINFO
471 sa.sa_flags = SA_SIGINFO;
472 if (fn == runtime_sighandler)
473 fn = (void *) sig_panic_info_handler;
474 sa.sa_sigaction = (void *) fn;
475 #else
476 sa.sa_flags = 0;
477 if (fn == runtime_sighandler)
478 fn = (void *) sig_panic_handler;
479 sa.sa_handler = (void *) fn;
480 #endif
481 }
482
483 if (restart)
484 sa.sa_flags |= SA_RESTART;
485
486 if (sigaction (t->sig, &sa, NULL) != 0)
487 __go_assert (0);
488 }
489
490 GoSighandler*
runtime_getsig(int32 i)491 runtime_getsig (int32 i)
492 {
493 struct sigaction sa;
494 int r;
495 SigTab *t;
496
497 memset (&sa, 0, sizeof sa);
498
499 r = sigemptyset (&sa.sa_mask);
500 __go_assert (r == 0);
501
502 t = &runtime_sigtab[i];
503
504 if (sigaction (t->sig, NULL, &sa) != 0)
505 runtime_throw ("sigaction read failure");
506
507 if ((void *) sa.sa_handler == sig_tramp_info)
508 return runtime_sighandler;
509 #ifdef SA_SIGINFO
510 if ((void *) sa.sa_handler == sig_panic_info_handler)
511 return runtime_sighandler;
512 #else
513 if ((void *) sa.sa_handler == sig_tramp
514 || (void *) sa.sa_handler == sig_panic_handler)
515 return runtime_sighandler;
516 #endif
517
518 return (void *) sa.sa_handler;
519 }
520
521 /* Used by the os package to raise SIGPIPE. */
522
523 void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe");
524
525 void
os_sigpipe(void)526 os_sigpipe (void)
527 {
528 struct sigaction sa;
529 int i;
530
531 if (__go_sigsend (SIGPIPE))
532 return;
533
534 memset (&sa, 0, sizeof sa);
535
536 sa.sa_handler = SIG_DFL;
537
538 i = sigemptyset (&sa.sa_mask);
539 __go_assert (i == 0);
540
541 if (sigaction (SIGPIPE, &sa, NULL) != 0)
542 abort ();
543
544 raise (SIGPIPE);
545 }
546
547 void
runtime_setprof(bool on)548 runtime_setprof(bool on)
549 {
550 USED(on);
551 }
552