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. */
13 #include "go-assert.h"
15 #include "signal_unix.h"
21 #ifdef USING_SPLIT_STACK
23 extern void __splitstack_getcontext(void *context
[10]);
25 extern void __splitstack_setcontext(void *context
[10]);
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
40 SigTab runtime_sigtab
[] = {
142 /* Handle a signal, for cases where we don't panic. We can split the
146 runtime_sighandler (int sig
, Siginfo
*info
,
147 void *context
__attribute__ ((unused
)), G
*gp
)
157 if (m
!= NULL
&& gp
!= m
->g0
&& gp
!= m
->gsignal
)
165 runtime_badsignal (sig
);
169 for (i
= 0; runtime_sigtab
[i
].sig
!= -1; ++i
)
174 t
= &runtime_sigtab
[i
];
181 notify
= info
!= NULL
&& info
->si_code
== SI_USER
;
183 if (notify
|| (t
->flags
& SigNotify
) != 0)
185 if (__go_sigsend (sig
))
188 if ((t
->flags
& SigKill
) != 0)
190 if ((t
->flags
& SigThrow
) == 0)
193 runtime_startpanic ();
196 const char *name
= NULL
;
198 #ifdef HAVE_STRSIGNAL
199 name
= strsignal (sig
);
203 runtime_printf ("Signal %d\n", sig
);
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");
214 runtime_printf ("\n");
216 if (runtime_gotraceback (&crash
))
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
235 __builtin_unreachable ();
238 /* The start of handling a signal which panics. */
241 sig_panic_leadin (int sig
)
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);
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. */
266 sig_panic_info_handler (int sig
, Siginfo
*info
, void *context
)
271 if (g
== NULL
|| info
->si_code
== SI_USER
)
273 runtime_sighandler (sig
, info
, context
, g
);
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
);
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");
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");
311 switch (info
->si_code
)
314 runtime_panicstring ("integer divide by zero");
316 runtime_panicstring ("integer overflow");
318 runtime_panicstring ("floating point error");
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) */
330 sig_panic_handler (int sig
)
337 runtime_sighandler (sig
, NULL
, NULL
, g
);
345 sig_panic_leadin (sig
);
351 runtime_panicstring ("invalid memory address or "
352 "nil pointer dereference");
357 runtime_panicstring ("invalid memory address or "
358 "nil pointer dereference");
363 runtime_panicstring ("integer divide by zero or floating point error");
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
379 sig_tramp_info (int, Siginfo
*, void *) __attribute__ ((no_split_stack
));
382 sig_tramp_info (int sig
, Siginfo
*info
, void *context
)
386 #ifdef USING_SPLIT_STACK
387 void *stack_context
[10];
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.) */
398 #ifdef USING_SPLIT_STACK
399 __splitstack_getcontext (&stack_context
[0]);
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]);
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
421 #ifdef USING_SPLIT_STACK
422 __splitstack_setcontext (&stack_context
[0]);
429 static void sig_tramp (int sig
) __attribute__ ((no_split_stack
));
434 sig_tramp_info (sig
, NULL
, NULL
);
440 runtime_setsig (int32 i
, GoSighandler
*fn
, bool restart
)
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)
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
;
461 sa
.sa_flags
= SA_ONSTACK
;
462 if (fn
== runtime_sighandler
)
463 fn
= (void *) sig_tramp
;
464 sa
.sa_handler
= (void *) fn
;
470 sa
.sa_flags
= SA_SIGINFO
;
471 if (fn
== runtime_sighandler
)
472 fn
= (void *) sig_panic_info_handler
;
473 sa
.sa_sigaction
= (void *) fn
;
476 if (fn
== runtime_sighandler
)
477 fn
= (void *) sig_panic_handler
;
478 sa
.sa_handler
= (void *) fn
;
483 sa
.sa_flags
|= SA_RESTART
;
485 if (sigaction (t
->sig
, &sa
, NULL
) != 0)
490 runtime_getsig (int32 i
)
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
;
509 if ((void *) sa
.sa_handler
== sig_panic_info_handler
)
510 return runtime_sighandler
;
512 if ((void *) sa
.sa_handler
== sig_tramp
513 || (void *) sa
.sa_handler
== sig_panic_handler
)
514 return runtime_sighandler
;
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");
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)
544 runtime_setprof(bool on
)