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)
163 t = &runtime_sigtab[i];
168 if ((t->flags & SigNotify) != 0)
170 if (__go_sigsend (sig))
173 if ((t->flags & SigKill) != 0)
175 if ((t->flags & SigThrow) == 0)
178 runtime_startpanic ();
180 /* We should do a stack backtrace here. Until we can do that,
181 we reraise the signal in order to get a slightly better
182 report from the shell. */
184 memset (&sa, 0, sizeof sa);
186 sa.sa_handler = SIG_DFL;
188 i = sigemptyset (&sa.sa_mask);
189 __go_assert (i == 0);
191 if (sigaction (sig, &sa, NULL) != 0)
199 __builtin_unreachable ();
202 /* The start of handling a signal which panics. */
205 sig_panic_leadin (int sig)
210 if (runtime_m ()->mallocing)
212 runtime_printf ("caught signal while mallocing: %d\n", sig);
213 runtime_throw ("caught signal while mallocing");
216 /* The signal handler blocked signals; unblock them. */
217 i = sigfillset (&clear);
218 __go_assert (i == 0);
219 i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
220 __go_assert (i == 0);
225 /* Signal dispatch for signals which panic, on systems which support
226 SA_SIGINFO. This is called on the thread stack, and as such it is
227 permitted to split the stack. */
230 sig_panic_info_handler (int sig, siginfo_t *info,
231 void *context __attribute__ ((unused)))
233 if (runtime_g () == NULL || info->si_code == SI_USER)
239 sig_panic_leadin (sig);
245 if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
246 runtime_panicstring ("invalid memory address or "
247 "nil pointer dereference");
248 runtime_printf ("unexpected fault address %p\n", info->si_addr);
249 runtime_throw ("fault");
254 if ((info->si_code == 0
255 || info->si_code == SEGV_MAPERR
256 || info->si_code == SEGV_ACCERR)
257 && (uintptr_t) info->si_addr < 0x1000)
258 runtime_panicstring ("invalid memory address or "
259 "nil pointer dereference");
260 runtime_printf ("unexpected fault address %p\n", info->si_addr);
261 runtime_throw ("fault");
266 switch (info->si_code)
269 runtime_panicstring ("integer divide by zero");
271 runtime_panicstring ("integer overflow");
273 runtime_panicstring ("floating point error");
277 /* All signals with SigPanic should be in cases above, and this
278 handler should only be invoked for those signals. */
279 __builtin_unreachable ();
282 #else /* !defined (SA_SIGINFO) */
285 sig_panic_handler (int sig)
287 if (runtime_g () == NULL)
293 sig_panic_leadin (sig);
299 runtime_panicstring ("invalid memory address or "
300 "nil pointer dereference");
305 runtime_panicstring ("invalid memory address or "
306 "nil pointer dereference");
311 runtime_panicstring ("integer divide by zero or floating point error");
315 /* All signals with SigPanic should be in cases above, and this
316 handler should only be invoked for those signals. */
317 __builtin_unreachable ();
320 #endif /* !defined (SA_SIGINFO) */
322 /* A signal handler used for signals which are not going to panic.
323 This is called on the alternate signal stack so it may not split
327 sig_tramp (int) __attribute__ ((no_split_stack));
335 /* We are now running on the stack registered via sigaltstack.
336 (Actually there is a small span of time between runtime_siginit
337 and sigaltstack when the program starts.) */
343 #ifdef USING_SPLIT_STACK
344 __splitstack_getcontext (&gp->stack_context[0]);
348 if (gp != NULL && mp->gsignal != NULL)
350 /* We are running on the signal stack. Set the split stack
351 context so that the stack guards are checked correctly. */
352 #ifdef USING_SPLIT_STACK
353 __splitstack_setcontext (&mp->gsignal->stack_context[0]);
359 /* We are going to return back to the signal trampoline and then to
360 whatever we were doing before we got the signal. Restore the
361 split stack context so that stack guards are checked
366 #ifdef USING_SPLIT_STACK
367 __splitstack_setcontext (&gp->stack_context[0]);
373 runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
379 memset (&sa, 0, sizeof sa);
381 r = sigfillset (&sa.sa_mask);
382 __go_assert (r == 0);
384 t = &runtime_sigtab[i];
386 if ((t->flags & SigPanic) == 0)
388 sa.sa_flags = SA_ONSTACK;
389 sa.sa_handler = sig_tramp;
394 sa.sa_flags = SA_SIGINFO;
395 sa.sa_sigaction = sig_panic_info_handler;
398 sa.sa_handler = sig_panic_handler;
403 sa.sa_flags |= SA_RESTART;
405 if (sigaction (t->sig, &sa, NULL) != 0)
409 /* Used by the os package to raise SIGPIPE. */
411 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
419 memset (&sa, 0, sizeof sa);
421 sa.sa_handler = SIG_DFL;
423 i = sigemptyset (&sa.sa_mask);
424 __go_assert (i == 0);
426 if (sigaction (SIGPIPE, &sa, NULL) != 0)
433 runtime_setprof(bool on)