2013-02-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
[official-gcc.git] / libgo / runtime / go-signal.c
blob1965e058816cd6611bae06f84cbacd17ae358002
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. */
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/time.h>
12 #include "runtime.h"
13 #include "go-assert.h"
14 #include "go-panic.h"
16 #ifndef SA_RESTART
17 #define SA_RESTART 0
18 #endif
20 #ifdef USING_SPLIT_STACK
22 extern void __splitstack_getcontext(void *context[10]);
24 extern void __splitstack_setcontext(void *context[10]);
26 #endif
28 #define N SigNotify
29 #define K SigKill
30 #define T SigThrow
31 #define P SigPanic
32 #define D SigDefault
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
37 them. */
39 SigTab runtime_sigtab[] = {
40 #ifdef SIGHUP
41 { SIGHUP, N + K },
42 #endif
43 #ifdef SIGINT
44 { SIGINT, N + K },
45 #endif
46 #ifdef SIGQUIT
47 { SIGQUIT, N + T },
48 #endif
49 #ifdef SIGILL
50 { SIGILL, T },
51 #endif
52 #ifdef SIGTRAP
53 { SIGTRAP, T },
54 #endif
55 #ifdef SIGABRT
56 { SIGABRT, N + T },
57 #endif
58 #ifdef SIGBUS
59 { SIGBUS, P },
60 #endif
61 #ifdef SIGFPE
62 { SIGFPE, P },
63 #endif
64 #ifdef SIGUSR1
65 { SIGUSR1, N },
66 #endif
67 #ifdef SIGSEGV
68 { SIGSEGV, P },
69 #endif
70 #ifdef SIGUSR2
71 { SIGUSR2, N },
72 #endif
73 #ifdef SIGPIPE
74 { SIGPIPE, N },
75 #endif
76 #ifdef SIGALRM
77 { SIGALRM, N },
78 #endif
79 #ifdef SIGTERM
80 { SIGTERM, N + K },
81 #endif
82 #ifdef SIGSTKFLT
83 { SIGSTKFLT, T },
84 #endif
85 #ifdef SIGCHLD
86 { SIGCHLD, N },
87 #endif
88 #ifdef SIGTSTP
89 { SIGTSTP, N + D },
90 #endif
91 #ifdef SIGTTIN
92 { SIGTTIN, N + D },
93 #endif
94 #ifdef SIGTTOU
95 { SIGTTOU, N + D },
96 #endif
97 #ifdef SIGURG
98 { SIGURG, N },
99 #endif
100 #ifdef SIGXCPU
101 { SIGXCPU, N },
102 #endif
103 #ifdef SIGXFSZ
104 { SIGXFSZ, N },
105 #endif
106 #ifdef SIGVTALRM
107 { SIGVTALRM, N },
108 #endif
109 #ifdef SIGPROF
110 { SIGPROF, N },
111 #endif
112 #ifdef SIGWINCH
113 { SIGWINCH, N },
114 #endif
115 #ifdef SIGIO
116 { SIGIO, N },
117 #endif
118 #ifdef SIGPWR
119 { SIGPWR, N },
120 #endif
121 #ifdef SIGSYS
122 { SIGSYS, N },
123 #endif
124 #ifdef SIGEMT
125 { SIGEMT, T },
126 #endif
127 #ifdef SIGINFO
128 { SIGINFO, N },
129 #endif
130 #ifdef SIGTHR
131 { SIGTHR, N },
132 #endif
133 { -1, 0 }
135 #undef N
136 #undef K
137 #undef T
138 #undef P
139 #undef D
142 static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
144 static void
145 runtime_badsignal(int32 sig)
147 // Avoid -D_FORTIFY_SOURCE problems.
148 int rv __attribute__((unused));
150 if (sig == SIGPROF) {
151 return; // Ignore SIGPROFs intended for a non-Go thread.
153 rv = runtime_write(2, badsignal, sizeof badsignal - 1);
154 runtime_exit(1);
157 /* Handle a signal, for cases where we don't panic. We can split the
158 stack here. */
160 static void
161 sig_handler (int sig)
163 int i;
165 if (runtime_m () == NULL)
167 runtime_badsignal (sig);
168 return;
171 #ifdef SIGPROF
172 if (sig == SIGPROF)
174 runtime_sigprof ();
175 return;
177 #endif
179 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
181 SigTab *t;
183 t = &runtime_sigtab[i];
185 if (t->sig != sig)
186 continue;
188 if ((t->flags & SigNotify) != 0)
190 if (__go_sigsend (sig))
191 return;
193 if ((t->flags & SigKill) != 0)
194 runtime_exit (2);
195 if ((t->flags & SigThrow) == 0)
196 return;
198 runtime_startpanic ();
201 const char *name = NULL;
203 #ifdef HAVE_STRSIGNAL
204 name = strsignal (sig);
205 #endif
207 if (name == NULL)
208 runtime_printf ("Signal %d\n", sig);
209 else
210 runtime_printf ("%s\n", name);
213 runtime_printf ("\n");
215 if (runtime_gotraceback ())
217 G *g;
219 g = runtime_g ();
220 runtime_traceback (g);
221 runtime_tracebackothers (g);
223 /* The gc library calls runtime_dumpregs here, and provides
224 a function that prints the registers saved in context in
225 a readable form. */
228 runtime_exit (2);
231 __builtin_unreachable ();
234 /* The start of handling a signal which panics. */
236 static void
237 sig_panic_leadin (int sig)
239 int i;
240 sigset_t clear;
242 if (runtime_m ()->mallocing)
244 runtime_printf ("caught signal while mallocing: %d\n", sig);
245 runtime_throw ("caught signal while mallocing");
248 /* The signal handler blocked signals; unblock them. */
249 i = sigfillset (&clear);
250 __go_assert (i == 0);
251 i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
252 __go_assert (i == 0);
255 #ifdef SA_SIGINFO
257 /* Signal dispatch for signals which panic, on systems which support
258 SA_SIGINFO. This is called on the thread stack, and as such it is
259 permitted to split the stack. */
261 static void
262 sig_panic_info_handler (int sig, siginfo_t *info,
263 void *context __attribute__ ((unused)))
265 G *g;
267 g = runtime_g ();
268 if (g == NULL || info->si_code == SI_USER)
270 sig_handler (sig);
271 return;
274 g->sig = sig;
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 (sig);
283 switch (sig)
285 #ifdef SIGBUS
286 case SIGBUS:
287 if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
288 runtime_panicstring ("invalid memory address or "
289 "nil pointer dereference");
290 runtime_printf ("unexpected fault address %p\n", info->si_addr);
291 runtime_throw ("fault");
292 #endif
294 #ifdef SIGSEGV
295 case SIGSEGV:
296 if ((info->si_code == 0
297 || info->si_code == SEGV_MAPERR
298 || info->si_code == SEGV_ACCERR)
299 && (uintptr_t) info->si_addr < 0x1000)
300 runtime_panicstring ("invalid memory address or "
301 "nil pointer dereference");
302 runtime_printf ("unexpected fault address %p\n", info->si_addr);
303 runtime_throw ("fault");
304 #endif
306 #ifdef SIGFPE
307 case SIGFPE:
308 switch (info->si_code)
310 case FPE_INTDIV:
311 runtime_panicstring ("integer divide by zero");
312 case FPE_INTOVF:
313 runtime_panicstring ("integer overflow");
315 runtime_panicstring ("floating point error");
316 #endif
319 /* All signals with SigPanic should be in cases above, and this
320 handler should only be invoked for those signals. */
321 __builtin_unreachable ();
324 #else /* !defined (SA_SIGINFO) */
326 static void
327 sig_panic_handler (int sig)
329 G *g;
331 g = runtime_g ();
332 if (g == NULL)
334 sig_handler (sig);
335 return;
338 g->sig = sig;
339 g->sigcode0 = 0;
340 g->sigcode1 = 0;
342 sig_panic_leadin (sig);
344 switch (sig)
346 #ifdef SIGBUS
347 case SIGBUS:
348 runtime_panicstring ("invalid memory address or "
349 "nil pointer dereference");
350 #endif
352 #ifdef SIGSEGV
353 case SIGSEGV:
354 runtime_panicstring ("invalid memory address or "
355 "nil pointer dereference");
356 #endif
358 #ifdef SIGFPE
359 case SIGFPE:
360 runtime_panicstring ("integer divide by zero or floating point error");
361 #endif
364 /* All signals with SigPanic should be in cases above, and this
365 handler should only be invoked for those signals. */
366 __builtin_unreachable ();
369 #endif /* !defined (SA_SIGINFO) */
371 /* A signal handler used for signals which are not going to panic.
372 This is called on the alternate signal stack so it may not split
373 the stack. */
375 static void
376 sig_tramp (int) __attribute__ ((no_split_stack));
378 static void
379 sig_tramp (int sig)
381 G *gp;
382 M *mp;
384 /* We are now running on the stack registered via sigaltstack.
385 (Actually there is a small span of time between runtime_siginit
386 and sigaltstack when the program starts.) */
387 gp = runtime_g ();
388 mp = runtime_m ();
390 if (gp != NULL)
392 #ifdef USING_SPLIT_STACK
393 __splitstack_getcontext (&gp->stack_context[0]);
394 #endif
397 if (gp != NULL && mp->gsignal != NULL)
399 /* We are running on the signal stack. Set the split stack
400 context so that the stack guards are checked correctly. */
401 #ifdef USING_SPLIT_STACK
402 __splitstack_setcontext (&mp->gsignal->stack_context[0]);
403 #endif
406 sig_handler (sig);
408 /* We are going to return back to the signal trampoline and then to
409 whatever we were doing before we got the signal. Restore the
410 split stack context so that stack guards are checked
411 correctly. */
413 if (gp != NULL)
415 #ifdef USING_SPLIT_STACK
416 __splitstack_setcontext (&gp->stack_context[0]);
417 #endif
421 void
422 runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
424 struct sigaction sa;
425 int r;
426 SigTab *t;
428 memset (&sa, 0, sizeof sa);
430 r = sigfillset (&sa.sa_mask);
431 __go_assert (r == 0);
433 t = &runtime_sigtab[i];
435 if ((t->flags & SigPanic) == 0)
437 sa.sa_flags = SA_ONSTACK;
438 sa.sa_handler = sig_tramp;
440 else
442 #ifdef SA_SIGINFO
443 sa.sa_flags = SA_SIGINFO;
444 sa.sa_sigaction = sig_panic_info_handler;
445 #else
446 sa.sa_flags = 0;
447 sa.sa_handler = sig_panic_handler;
448 #endif
451 if (restart)
452 sa.sa_flags |= SA_RESTART;
454 if (sigaction (t->sig, &sa, NULL) != 0)
455 __go_assert (0);
458 /* Used by the os package to raise SIGPIPE. */
460 void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe");
462 void
463 os_sigpipe (void)
465 struct sigaction sa;
466 int i;
468 memset (&sa, 0, sizeof sa);
470 sa.sa_handler = SIG_DFL;
472 i = sigemptyset (&sa.sa_mask);
473 __go_assert (i == 0);
475 if (sigaction (SIGPIPE, &sa, NULL) != 0)
476 abort ();
478 raise (SIGPIPE);
481 void
482 runtime_setprof(bool on)
484 USED(on);