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"
20 #ifdef USING_SPLIT_STACK
22 extern void __splitstack_getcontext(void *context[10]);
24 extern void __splitstack_setcontext(void *context[10]);
34 /* Signal actions. This collects the sigtab tables for several
35 different targets from the master library. SIGKILL, SIGCONT, and
36 SIGSTOP are not listed, as we don't want to set signal handlers for
39 SigTab runtime_sigtab[] = {
141 /* Handle a signal, for cases where we don't panic. We can split the
145 sig_handler (int sig)
153 runtime_sigprof (0, 0, nil, nil);
158 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
162 t = &runtime_sigtab[i];
167 if ((t->flags & SigNotify) != 0)
169 if (__go_sigsend (sig))
172 if ((t->flags & SigKill) != 0)
174 if ((t->flags & SigThrow) == 0)
177 runtime_startpanic ();
180 const char *name = NULL;
182 #ifdef HAVE_STRSIGNAL
183 name = strsignal (sig);
187 runtime_printf ("Signal %d\n", sig);
189 runtime_printf ("%s\n", name);
192 runtime_printf ("\n");
194 if (runtime_gotraceback ())
199 runtime_traceback (g);
200 runtime_tracebackothers (g);
202 /* The gc library calls runtime_dumpregs here, and provides
203 a function that prints the registers saved in context in
210 __builtin_unreachable ();
213 /* The start of handling a signal which panics. */
216 sig_panic_leadin (int sig)
221 if (runtime_m ()->mallocing)
223 runtime_printf ("caught signal while mallocing: %d\n", sig);
224 runtime_throw ("caught signal while mallocing");
227 /* The signal handler blocked signals; unblock them. */
228 i = sigfillset (&clear);
229 __go_assert (i == 0);
230 i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
231 __go_assert (i == 0);
236 /* Signal dispatch for signals which panic, on systems which support
237 SA_SIGINFO. This is called on the thread stack, and as such it is
238 permitted to split the stack. */
241 sig_panic_info_handler (int sig, siginfo_t *info,
242 void *context __attribute__ ((unused)))
247 if (g == NULL || info->si_code == SI_USER)
254 g->sigcode0 = info->si_code;
255 g->sigcode1 = (uintptr_t) info->si_addr;
257 /* It would be nice to set g->sigpc here as the gc library does, but
258 I don't know how to get it portably. */
260 sig_panic_leadin (sig);
266 if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
267 runtime_panicstring ("invalid memory address or "
268 "nil pointer dereference");
269 runtime_printf ("unexpected fault address %p\n", info->si_addr);
270 runtime_throw ("fault");
275 if ((info->si_code == 0
276 || info->si_code == SEGV_MAPERR
277 || info->si_code == SEGV_ACCERR)
278 && (uintptr_t) info->si_addr < 0x1000)
279 runtime_panicstring ("invalid memory address or "
280 "nil pointer dereference");
281 runtime_printf ("unexpected fault address %p\n", info->si_addr);
282 runtime_throw ("fault");
287 switch (info->si_code)
290 runtime_panicstring ("integer divide by zero");
292 runtime_panicstring ("integer overflow");
294 runtime_panicstring ("floating point error");
298 /* All signals with SigPanic should be in cases above, and this
299 handler should only be invoked for those signals. */
300 __builtin_unreachable ();
303 #else /* !defined (SA_SIGINFO) */
306 sig_panic_handler (int sig)
321 sig_panic_leadin (sig);
327 runtime_panicstring ("invalid memory address or "
328 "nil pointer dereference");
333 runtime_panicstring ("invalid memory address or "
334 "nil pointer dereference");
339 runtime_panicstring ("integer divide by zero or floating point error");
343 /* All signals with SigPanic should be in cases above, and this
344 handler should only be invoked for those signals. */
345 __builtin_unreachable ();
348 #endif /* !defined (SA_SIGINFO) */
350 /* A signal handler used for signals which are not going to panic.
351 This is called on the alternate signal stack so it may not split
355 sig_tramp (int) __attribute__ ((no_split_stack));
363 /* We are now running on the stack registered via sigaltstack.
364 (Actually there is a small span of time between runtime_siginit
365 and sigaltstack when the program starts.) */
371 #ifdef USING_SPLIT_STACK
372 __splitstack_getcontext (&gp->stack_context[0]);
376 if (gp != NULL && mp->gsignal != NULL)
378 /* We are running on the signal stack. Set the split stack
379 context so that the stack guards are checked correctly. */
380 #ifdef USING_SPLIT_STACK
381 __splitstack_setcontext (&mp->gsignal->stack_context[0]);
387 /* We are going to return back to the signal trampoline and then to
388 whatever we were doing before we got the signal. Restore the
389 split stack context so that stack guards are checked
394 #ifdef USING_SPLIT_STACK
395 __splitstack_setcontext (&gp->stack_context[0]);
401 runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
407 memset (&sa, 0, sizeof sa);
409 r = sigfillset (&sa.sa_mask);
410 __go_assert (r == 0);
412 t = &runtime_sigtab[i];
414 if ((t->flags & SigPanic) == 0)
416 sa.sa_flags = SA_ONSTACK;
417 sa.sa_handler = sig_tramp;
422 sa.sa_flags = SA_SIGINFO;
423 sa.sa_sigaction = sig_panic_info_handler;
426 sa.sa_handler = sig_panic_handler;
431 sa.sa_flags |= SA_RESTART;
433 if (sigaction (t->sig, &sa, NULL) != 0)
437 /* Used by the os package to raise SIGPIPE. */
439 void os_sigpipe (void) __asm__ ("os.sigpipe");
447 memset (&sa, 0, sizeof sa);
449 sa.sa_handler = SIG_DFL;
451 i = sigemptyset (&sa.sa_mask);
452 __go_assert (i == 0);
454 if (sigaction (SIGPIPE, &sa, NULL) != 0)
461 runtime_setprof(bool on)