2012-01-13 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / runtime / go-signal.c
blobfd48f4ba659356b45bd67dcf8e0ac8eec2f5320d
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 C SigCatch
29 #define I SigIgnore
30 #define R SigRestart
31 #define Q SigQueue
32 #define P SigPanic
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, Q + R },
42 #endif
43 #ifdef SIGINT
44 { SIGINT, Q + R },
45 #endif
46 #ifdef SIGQUIT
47 { SIGQUIT, C },
48 #endif
49 #ifdef SIGILL
50 { SIGILL, C },
51 #endif
52 #ifdef SIGTRAP
53 { SIGTRAP, C },
54 #endif
55 #ifdef SIGABRT
56 { SIGABRT, C },
57 #endif
58 #ifdef SIGBUS
59 { SIGBUS, C + P },
60 #endif
61 #ifdef SIGFPE
62 { SIGFPE, C + P },
63 #endif
64 #ifdef SIGUSR1
65 { SIGUSR1, Q + I + R },
66 #endif
67 #ifdef SIGSEGV
68 { SIGSEGV, C + P },
69 #endif
70 #ifdef SIGUSR2
71 { SIGUSR2, Q + I + R },
72 #endif
73 #ifdef SIGPIPE
74 { SIGPIPE, I },
75 #endif
76 #ifdef SIGALRM
77 { SIGALRM, Q + I + R },
78 #endif
79 #ifdef SIGTERM
80 { SIGTERM, Q + R },
81 #endif
82 #ifdef SIGSTKFLT
83 { SIGSTKFLT, C },
84 #endif
85 #ifdef SIGCHLD
86 { SIGCHLD, Q + I + R },
87 #endif
88 #ifdef SIGTSTP
89 { SIGTSTP, Q + I + R },
90 #endif
91 #ifdef SIGTTIN
92 { SIGTTIN, Q + I + R },
93 #endif
94 #ifdef SIGTTOU
95 { SIGTTOU, Q + I + R },
96 #endif
97 #ifdef SIGURG
98 { SIGURG, Q + I + R },
99 #endif
100 #ifdef SIGXCPU
101 { SIGXCPU, Q + I + R },
102 #endif
103 #ifdef SIGXFSZ
104 { SIGXFSZ, Q + I + R },
105 #endif
106 #ifdef SIGVTALRM
107 { SIGVTALRM, Q + I + R },
108 #endif
109 #ifdef SIGPROF
110 { SIGPROF, Q + I + R },
111 #endif
112 #ifdef SIGWINCH
113 { SIGWINCH, Q + I + R },
114 #endif
115 #ifdef SIGIO
116 { SIGIO, Q + I + R },
117 #endif
118 #ifdef SIGPWR
119 { SIGPWR, Q + I + R },
120 #endif
121 #ifdef SIGSYS
122 { SIGSYS, C },
123 #endif
124 #ifdef SIGEMT
125 { SIGEMT, C },
126 #endif
127 #ifdef SIGINFO
128 { SIGINFO, Q + I + R },
129 #endif
130 #ifdef SIGTHR
131 { SIGTHR, Q + I + R },
132 #endif
133 { -1, 0 }
135 #undef C
136 #undef I
137 #undef R
138 #undef Q
139 #undef P
141 /* Handle a signal, for cases where we don't panic. We can split the
142 stack here. */
144 static void
145 sig_handler (int sig)
147 int i;
149 #ifdef SIGPROF
150 if (sig == SIGPROF)
152 /* FIXME. */
153 runtime_sigprof (0, 0, nil, nil);
154 return;
156 #endif
158 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
160 struct sigaction sa;
162 if (runtime_sigtab[i].sig != sig)
163 continue;
165 if ((runtime_sigtab[i].flags & SigQueue) != 0)
167 if (__go_sigsend (sig)
168 || (runtime_sigtab[sig].flags & SigIgnore) != 0)
169 return;
170 runtime_exit (2); // SIGINT, SIGTERM, etc
173 if (runtime_panicking)
174 runtime_exit (2);
175 runtime_panicking = 1;
177 /* We should do a stack backtrace here. Until we can do that,
178 we reraise the signal in order to get a slightly better
179 report from the shell. */
181 memset (&sa, 0, sizeof sa);
183 sa.sa_handler = SIG_DFL;
185 i = sigemptyset (&sa.sa_mask);
186 __go_assert (i == 0);
188 if (sigaction (sig, &sa, NULL) != 0)
189 abort ();
191 raise (sig);
193 runtime_exit (2);
196 __builtin_unreachable ();
199 /* The start of handling a signal which panics. */
201 static void
202 sig_panic_leadin (int sig)
204 int i;
205 sigset_t clear;
207 if (runtime_m ()->mallocing)
209 runtime_printf ("caught signal while mallocing: %d\n", sig);
210 runtime_throw ("caught signal while mallocing");
213 /* The signal handler blocked signals; unblock them. */
214 i = sigfillset (&clear);
215 __go_assert (i == 0);
216 i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
217 __go_assert (i == 0);
220 #ifdef SA_SIGINFO
222 /* Signal dispatch for signals which panic, on systems which support
223 SA_SIGINFO. This is called on the thread stack, and as such it is
224 permitted to split the stack. */
226 static void
227 sig_panic_info_handler (int sig, siginfo_t *info,
228 void *context __attribute__ ((unused)))
230 if (runtime_g () == NULL)
232 sig_handler (sig);
233 return;
236 sig_panic_leadin (sig);
238 switch (sig)
240 #ifdef SIGBUS
241 case SIGBUS:
242 if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
243 runtime_panicstring ("invalid memory address or "
244 "nil pointer dereference");
245 runtime_printf ("unexpected fault address %p\n", info->si_addr);
246 runtime_throw ("fault");
247 #endif
249 #ifdef SIGSEGV
250 case SIGSEGV:
251 if ((info->si_code == 0
252 || info->si_code == SEGV_MAPERR
253 || info->si_code == SEGV_ACCERR)
254 && (uintptr_t) info->si_addr < 0x1000)
255 runtime_panicstring ("invalid memory address or "
256 "nil pointer dereference");
257 runtime_printf ("unexpected fault address %p\n", info->si_addr);
258 runtime_throw ("fault");
259 #endif
261 #ifdef SIGFPE
262 case SIGFPE:
263 switch (info->si_code)
265 case FPE_INTDIV:
266 runtime_panicstring ("integer divide by zero");
267 case FPE_INTOVF:
268 runtime_panicstring ("integer overflow");
270 runtime_panicstring ("floating point error");
271 #endif
274 /* All signals with SigPanic should be in cases above, and this
275 handler should only be invoked for those signals. */
276 __builtin_unreachable ();
279 #else /* !defined (SA_SIGINFO) */
281 static void
282 sig_panic_handler (int sig)
284 if (runtime_g () == NULL)
286 sig_handler (sig);
287 return;
290 sig_panic_leadin (sig);
292 switch (sig)
294 #ifdef SIGBUS
295 case SIGBUS:
296 runtime_panicstring ("invalid memory address or "
297 "nil pointer dereference");
298 #endif
300 #ifdef SIGSEGV
301 case SIGSEGV:
302 runtime_panicstring ("invalid memory address or "
303 "nil pointer dereference");
304 #endif
306 #ifdef SIGFPE
307 case SIGFPE:
308 runtime_panicstring ("integer divide by zero or floating point error");
309 #endif
312 /* All signals with SigPanic should be in cases above, and this
313 handler should only be invoked for those signals. */
314 __builtin_unreachable ();
317 #endif /* !defined (SA_SIGINFO) */
319 /* Ignore a signal. This is called on the alternate signal stack so
320 it may not split the stack. */
322 static void sig_ignore (int) __attribute__ ((no_split_stack));
324 static void
325 sig_ignore (int sig __attribute__ ((unused)))
329 /* A signal handler used for signals which are not going to panic.
330 This is called on the alternate signal stack so it may not split
331 the stack. */
333 static void
334 sig_tramp (int) __attribute__ ((no_split_stack));
336 static void
337 sig_tramp (int sig)
339 G *gp;
340 M *mp;
342 /* We are now running on the stack registered via sigaltstack.
343 (Actually there is a small span of time between runtime_siginit
344 and sigaltstack when the program starts.) */
345 gp = runtime_g ();
346 mp = runtime_m ();
348 if (gp != NULL)
350 #ifdef USING_SPLIT_STACK
351 __splitstack_getcontext (&gp->stack_context[0]);
352 #endif
355 if (gp != NULL && mp->gsignal != NULL)
357 /* We are running on the signal stack. Set the split stack
358 context so that the stack guards are checked correctly. */
359 #ifdef USING_SPLIT_STACK
360 __splitstack_setcontext (&mp->gsignal->stack_context[0]);
361 #endif
364 sig_handler (sig);
366 /* We are going to return back to the signal trampoline and then to
367 whatever we were doing before we got the signal. Restore the
368 split stack context so that stack guards are checked
369 correctly. */
371 if (gp != NULL)
373 #ifdef USING_SPLIT_STACK
374 __splitstack_setcontext (&gp->stack_context[0]);
375 #endif
379 /* Initialize signal handling for Go. This is called when the program
380 starts. */
382 void
383 runtime_initsig (int32 queue)
385 struct sigaction sa;
386 int i;
388 siginit ();
390 memset (&sa, 0, sizeof sa);
392 i = sigfillset (&sa.sa_mask);
393 __go_assert (i == 0);
395 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
397 if (runtime_sigtab[i].flags == 0)
398 continue;
399 if ((runtime_sigtab[i].flags & SigQueue) != queue)
400 continue;
402 if ((runtime_sigtab[i].flags & (SigCatch | SigQueue)) != 0)
404 if ((runtime_sigtab[i].flags & SigPanic) == 0)
406 sa.sa_flags = SA_ONSTACK;
407 sa.sa_handler = sig_tramp;
409 else
411 #ifdef SA_SIGINFO
412 sa.sa_flags = SA_SIGINFO;
413 sa.sa_sigaction = sig_panic_info_handler;
414 #else
415 sa.sa_flags = 0;
416 sa.sa_handler = sig_panic_handler;
417 #endif
420 else
422 sa.sa_flags = SA_ONSTACK;
423 sa.sa_handler = sig_ignore;
426 if ((runtime_sigtab[i].flags & SigRestart) != 0)
427 sa.sa_flags |= SA_RESTART;
429 if (sigaction (runtime_sigtab[i].sig, &sa, NULL) != 0)
430 __go_assert (0);
434 void
435 runtime_resetcpuprofiler(int32 hz)
437 #ifdef SIGPROF
438 struct itimerval it;
439 struct sigaction sa;
440 int i;
442 memset (&it, 0, sizeof it);
444 memset (&sa, 0, sizeof sa);
445 i = sigfillset (&sa.sa_mask);
446 __go_assert (i == 0);
448 if (hz == 0)
450 i = setitimer (ITIMER_PROF, &it, NULL);
451 __go_assert (i == 0);
453 sa.sa_handler = SIG_IGN;
454 i = sigaction (SIGPROF, &sa, NULL);
455 __go_assert (i == 0);
457 else
459 sa.sa_handler = sig_handler;
460 sa.sa_flags = SA_RESTART;
461 i = sigaction (SIGPROF, &sa, NULL);
462 __go_assert (i == 0);
464 it.it_interval.tv_sec = 0;
465 it.it_interval.tv_usec = 1000000 / hz;
466 it.it_value = it.it_interval;
467 i = setitimer (ITIMER_PROF, &it, NULL);
468 __go_assert (i == 0);
470 #endif
472 runtime_m()->profilehz = hz;
475 /* Used by the os package to raise SIGPIPE. */
477 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
479 void
480 os_sigpipe (void)
482 struct sigaction sa;
483 int i;
485 memset (&sa, 0, sizeof sa);
487 sa.sa_handler = SIG_DFL;
489 i = sigemptyset (&sa.sa_mask);
490 __go_assert (i == 0);
492 if (sigaction (SIGPIPE, &sa, NULL) != 0)
493 abort ();
495 raise (SIGPIPE);