OSDN Git Service

syscall: Fill out GNU/Linux support.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-signal.c
1 /* go-signal.c -- signal handling for Go.
2
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.  */
6
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/time.h>
11
12 #include "runtime.h"
13 #include "go-assert.h"
14 #include "go-panic.h"
15
16 #ifndef SA_RESTART
17   #define SA_RESTART 0
18 #endif
19
20 #ifdef USING_SPLIT_STACK
21
22 extern void __splitstack_getcontext(void *context[10]);
23
24 extern void __splitstack_setcontext(void *context[10]);
25
26 #endif
27
28 #define C SigCatch
29 #define I SigIgnore
30 #define R SigRestart
31 #define Q SigQueue
32 #define P SigPanic
33
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.  */
38
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 }
134 };
135 #undef C
136 #undef I
137 #undef R
138 #undef Q
139 #undef P
140
141 /* Handle a signal, for cases where we don't panic.  We can split the
142    stack here.  */
143
144 static void
145 sig_handler (int sig)
146 {
147   int i;
148
149 #ifdef SIGPROF
150   if (sig == SIGPROF)
151     {
152       /* FIXME.  */
153       runtime_sigprof (0, 0, nil, nil);
154       return;
155     }
156 #endif
157
158   for (i = 0; runtime_sigtab[i].sig != -1; ++i)
159     {
160       struct sigaction sa;
161
162       if (runtime_sigtab[i].sig != sig)
163         continue;
164
165       if ((runtime_sigtab[i].flags & SigQueue) != 0)
166         {
167           if (__go_sigsend (sig)
168               || (runtime_sigtab[sig].flags & SigIgnore) != 0)
169             return;
170           runtime_exit (2);             // SIGINT, SIGTERM, etc
171         }
172
173       if (runtime_panicking)
174         runtime_exit (2);
175       runtime_panicking = 1;
176
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.  */
180
181       memset (&sa, 0, sizeof sa);
182
183       sa.sa_handler = SIG_DFL;
184
185       i = sigemptyset (&sa.sa_mask);
186       __go_assert (i == 0);
187
188       if (sigaction (sig, &sa, NULL) != 0)
189         abort ();
190
191       raise (sig);
192
193       runtime_exit (2);
194     }
195
196   __builtin_unreachable ();
197 }
198
199 /* The start of handling a signal which panics.  */
200
201 static void
202 sig_panic_leadin (int sig)
203 {
204   int i;
205   sigset_t clear;
206
207   if (runtime_m ()->mallocing)
208     {
209       runtime_printf ("caught signal while mallocing: %d\n", sig);
210       runtime_throw ("caught signal while mallocing");
211     }
212
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);
218 }
219
220 #ifdef SA_SIGINFO
221
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.  */
225
226 static void
227 sig_panic_info_handler (int sig, siginfo_t *info,
228                         void *context __attribute__ ((unused)))
229 {
230   if (runtime_g () == NULL)
231     {
232       sig_handler (sig);
233       return;
234     }
235
236   sig_panic_leadin (sig);
237
238   switch (sig)
239     {
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
248
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
260
261 #ifdef SIGFPE
262     case SIGFPE:
263       switch (info->si_code)
264         {
265         case FPE_INTDIV:
266           runtime_panicstring ("integer divide by zero");
267         case FPE_INTOVF:
268           runtime_panicstring ("integer overflow");
269         }
270       runtime_panicstring ("floating point error");
271 #endif
272     }
273
274   /* All signals with SigPanic should be in cases above, and this
275      handler should only be invoked for those signals.  */
276   __builtin_unreachable ();
277 }
278
279 #else /* !defined (SA_SIGINFO) */
280
281 static void
282 sig_panic_handler (int sig)
283 {
284   if (runtime_g () == NULL)
285     {
286       sig_handler (sig);
287       return;
288     }
289
290   sig_panic_leadin (sig);
291
292   switch (sig)
293     {
294 #ifdef SIGBUS
295     case SIGBUS:
296       runtime_panicstring ("invalid memory address or "
297                            "nil pointer dereference");
298 #endif
299
300 #ifdef SIGSEGV
301     case SIGSEGV:
302       runtime_panicstring ("invalid memory address or "
303                            "nil pointer dereference");
304 #endif
305
306 #ifdef SIGFPE
307     case SIGFPE:
308       runtime_panicstring ("integer divide by zero or floating point error");
309 #endif
310     }
311
312   /* All signals with SigPanic should be in cases above, and this
313      handler should only be invoked for those signals.  */
314   __builtin_unreachable ();
315 }
316
317 #endif /* !defined (SA_SIGINFO) */
318
319 /* Ignore a signal.  This is called on the alternate signal stack so
320    it may not split the stack.  */
321
322 static void sig_ignore (int) __attribute__ ((no_split_stack));
323
324 static void
325 sig_ignore (int sig __attribute__ ((unused)))
326 {
327 }
328
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.  */
332
333 static void
334 sig_tramp (int) __attribute__ ((no_split_stack));
335
336 static void
337 sig_tramp (int sig)
338 {
339   G *gp;
340   M *mp;
341
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 ();
347
348   if (gp != NULL)
349     {
350 #ifdef USING_SPLIT_STACK
351       __splitstack_getcontext (&gp->stack_context[0]);
352 #endif
353     }
354
355   if (gp != NULL && mp->gsignal != NULL)
356     {
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
362     }
363
364   sig_handler (sig);
365
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.  */
370
371   if (gp != NULL)
372     {
373 #ifdef USING_SPLIT_STACK
374       __splitstack_setcontext (&gp->stack_context[0]);
375 #endif
376     }
377 }
378
379 /* Initialize signal handling for Go.  This is called when the program
380    starts.  */
381
382 void
383 runtime_initsig (int32 queue)
384 {
385   struct sigaction sa;
386   int i;
387
388   siginit ();
389
390   memset (&sa, 0, sizeof sa);
391
392   i = sigfillset (&sa.sa_mask);
393   __go_assert (i == 0);
394
395   for (i = 0; runtime_sigtab[i].sig != -1; ++i)
396     {
397       if (runtime_sigtab[i].flags == 0)
398         continue;
399       if ((runtime_sigtab[i].flags & SigQueue) != queue)
400         continue;
401
402       if ((runtime_sigtab[i].flags & (SigCatch | SigQueue)) != 0)
403         {
404           if ((runtime_sigtab[i].flags & SigPanic) == 0)
405             {
406               sa.sa_flags = SA_ONSTACK;
407               sa.sa_handler = sig_tramp;
408             }
409           else
410             {
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
418             }
419         }
420       else
421         {
422           sa.sa_flags = SA_ONSTACK;
423           sa.sa_handler = sig_ignore;
424         }
425
426       if ((runtime_sigtab[i].flags & SigRestart) != 0)
427         sa.sa_flags |= SA_RESTART;
428
429       if (sigaction (runtime_sigtab[i].sig, &sa, NULL) != 0)
430         __go_assert (0);
431     }
432 }
433
434 void
435 runtime_resetcpuprofiler(int32 hz)
436 {
437 #ifdef SIGPROF
438   struct itimerval it;
439   struct sigaction sa;
440   int i;
441
442   memset (&it, 0, sizeof it);
443
444   memset (&sa, 0, sizeof sa);
445   i = sigfillset (&sa.sa_mask);
446   __go_assert (i == 0);
447
448   if (hz == 0)
449     {
450       i = setitimer (ITIMER_PROF, &it, NULL);
451       __go_assert (i == 0);
452
453       sa.sa_handler = SIG_IGN;
454       i = sigaction (SIGPROF, &sa, NULL);
455       __go_assert (i == 0);
456     }
457   else
458     {
459       sa.sa_handler = sig_handler;
460       sa.sa_flags = SA_RESTART;
461       i = sigaction (SIGPROF, &sa, NULL);
462       __go_assert (i == 0);
463
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);
469     }
470 #endif
471
472   runtime_m()->profilehz = hz;
473 }
474
475 /* Used by the os package to raise SIGPIPE.  */
476
477 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
478
479 void
480 os_sigpipe (void)
481 {
482   struct sigaction sa;
483   int i;
484
485   memset (&sa, 0, sizeof sa);
486
487   sa.sa_handler = SIG_DFL;
488
489   i = sigemptyset (&sa.sa_mask);
490   __go_assert (i == 0);
491
492   if (sigaction (SIGPIPE, &sa, NULL) != 0)
493     abort ();
494
495   raise (SIGPIPE);
496 }