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 (G
*gp
)
246 if (!runtime_canpanic (gp
))
247 runtime_throw ("unexpected signal during runtime execution");
249 /* The signal handler blocked signals; unblock them. */
250 i
= sigfillset (&clear
);
251 __go_assert (i
== 0);
252 i
= pthread_sigmask (SIG_UNBLOCK
, &clear
, NULL
);
253 __go_assert (i
== 0);
258 /* Signal dispatch for signals which panic, on systems which support
259 SA_SIGINFO. This is called on the thread stack, and as such it is
260 permitted to split the stack. */
263 sig_panic_info_handler (int sig
, Siginfo
*info
, void *context
)
268 if (g
== NULL
|| info
->si_code
== SI_USER
)
270 runtime_sighandler (sig
, info
, context
, g
);
275 g
->sigcode0
= info
->si_code
;
276 g
->sigcode1
= (uintptr_t) info
->si_addr
;
278 /* It would be nice to set g->sigpc here as the gc library does, but
279 I don't know how to get it portably. */
281 sig_panic_leadin (g
);
287 if ((info
->si_code
== BUS_ADRERR
&& (uintptr_t) info
->si_addr
< 0x1000)
289 runtime_panicstring ("invalid memory address or "
290 "nil pointer dereference");
291 runtime_printf ("unexpected fault address %p\n", info
->si_addr
);
292 runtime_throw ("fault");
297 if (((info
->si_code
== 0
298 || info
->si_code
== SEGV_MAPERR
299 || info
->si_code
== SEGV_ACCERR
)
300 && (uintptr_t) info
->si_addr
< 0x1000)
302 runtime_panicstring ("invalid memory address or "
303 "nil pointer dereference");
304 runtime_printf ("unexpected fault address %p\n", info
->si_addr
);
305 runtime_throw ("fault");
310 switch (info
->si_code
)
313 runtime_panicstring ("integer divide by zero");
315 runtime_panicstring ("integer overflow");
317 runtime_panicstring ("floating point error");
321 /* All signals with SigPanic should be in cases above, and this
322 handler should only be invoked for those signals. */
323 __builtin_unreachable ();
326 #else /* !defined (SA_SIGINFO) */
329 sig_panic_handler (int sig
)
336 runtime_sighandler (sig
, NULL
, NULL
, g
);
344 sig_panic_leadin (g
);
350 runtime_panicstring ("invalid memory address or "
351 "nil pointer dereference");
356 runtime_panicstring ("invalid memory address or "
357 "nil pointer dereference");
362 runtime_panicstring ("integer divide by zero or floating point error");
366 /* All signals with SigPanic should be in cases above, and this
367 handler should only be invoked for those signals. */
368 __builtin_unreachable ();
371 #endif /* !defined (SA_SIGINFO) */
373 /* A signal handler used for signals which are not going to panic.
374 This is called on the alternate signal stack so it may not split
378 sig_tramp_info (int, Siginfo
*, void *) __attribute__ ((no_split_stack
));
381 sig_tramp_info (int sig
, Siginfo
*info
, void *context
)
385 #ifdef USING_SPLIT_STACK
386 void *stack_context
[10];
389 /* We are now running on the stack registered via sigaltstack.
390 (Actually there is a small span of time between runtime_siginit
391 and sigaltstack when the program starts.) */
397 #ifdef USING_SPLIT_STACK
398 __splitstack_getcontext (&stack_context
[0]);
402 if (gp
!= NULL
&& mp
->gsignal
!= NULL
)
404 /* We are running on the signal stack. Set the split stack
405 context so that the stack guards are checked correctly. */
406 #ifdef USING_SPLIT_STACK
407 __splitstack_setcontext (&mp
->gsignal
->stack_context
[0]);
411 runtime_sighandler (sig
, info
, context
, gp
);
413 /* We are going to return back to the signal trampoline and then to
414 whatever we were doing before we got the signal. Restore the
415 split stack context so that stack guards are checked
420 #ifdef USING_SPLIT_STACK
421 __splitstack_setcontext (&stack_context
[0]);
428 static void sig_tramp (int sig
) __attribute__ ((no_split_stack
));
433 sig_tramp_info (sig
, NULL
, NULL
);
439 runtime_setsig (int32 i
, GoSighandler
*fn
, bool restart
)
445 memset (&sa
, 0, sizeof sa
);
447 r
= sigfillset (&sa
.sa_mask
);
448 __go_assert (r
== 0);
450 t
= &runtime_sigtab
[i
];
452 if ((t
->flags
& SigPanic
) == 0)
455 sa
.sa_flags
= SA_ONSTACK
| SA_SIGINFO
;
456 if (fn
== runtime_sighandler
)
457 fn
= (void *) sig_tramp_info
;
458 sa
.sa_sigaction
= (void *) fn
;
460 sa
.sa_flags
= SA_ONSTACK
;
461 if (fn
== runtime_sighandler
)
462 fn
= (void *) sig_tramp
;
463 sa
.sa_handler
= (void *) fn
;
469 sa
.sa_flags
= SA_SIGINFO
;
470 if (fn
== runtime_sighandler
)
471 fn
= (void *) sig_panic_info_handler
;
472 sa
.sa_sigaction
= (void *) fn
;
475 if (fn
== runtime_sighandler
)
476 fn
= (void *) sig_panic_handler
;
477 sa
.sa_handler
= (void *) fn
;
482 sa
.sa_flags
|= SA_RESTART
;
484 if (sigaction (t
->sig
, &sa
, NULL
) != 0)
489 runtime_getsig (int32 i
)
495 memset (&sa
, 0, sizeof sa
);
497 r
= sigemptyset (&sa
.sa_mask
);
498 __go_assert (r
== 0);
500 t
= &runtime_sigtab
[i
];
502 if (sigaction (t
->sig
, NULL
, &sa
) != 0)
503 runtime_throw ("sigaction read failure");
505 if ((void *) sa
.sa_handler
== sig_tramp_info
)
506 return runtime_sighandler
;
508 if ((void *) sa
.sa_handler
== sig_panic_info_handler
)
509 return runtime_sighandler
;
511 if ((void *) sa
.sa_handler
== sig_tramp
512 || (void *) sa
.sa_handler
== sig_panic_handler
)
513 return runtime_sighandler
;
516 return (void *) sa
.sa_handler
;
519 /* Used by the os package to raise SIGPIPE. */
521 void os_sigpipe (void) __asm__ (GOSYM_PREFIX
"os.sigpipe");
529 memset (&sa
, 0, sizeof sa
);
531 sa
.sa_handler
= SIG_DFL
;
533 i
= sigemptyset (&sa
.sa_mask
);
534 __go_assert (i
== 0);
536 if (sigaction (SIGPIPE
, &sa
, NULL
) != 0)
543 runtime_setprof(bool on
)