OSDN Git Service

e5a790aae52e3b49992cea073141418f4bc8288c
[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     __splitstack_getcontext (&gp->stack_context[0]);
350
351   if (gp != NULL && mp->gsignal != NULL)
352     {
353       /* We are running on the signal stack.  Set the split stack
354          context so that the stack guards are checked correctly.  */
355 #ifdef USING_SPLIT_STACK
356       __splitstack_setcontext (&mp->gsignal->stack_context[0]);
357 #endif
358     }
359
360   sig_handler (sig);
361
362   /* We are going to return back to the signal trampoline and then to
363      whatever we were doing before we got the signal.  Restore the
364      split stack context so that stack guards are checked
365      correctly.  */
366
367   if (gp != NULL)
368     {
369 #ifdef USING_SPLIT_STACK
370       __splitstack_setcontext (&gp->stack_context[0]);
371 #endif
372     }
373 }
374
375 /* Initialize signal handling for Go.  This is called when the program
376    starts.  */
377
378 void
379 runtime_initsig (int32 queue)
380 {
381   struct sigaction sa;
382   int i;
383
384   siginit ();
385
386   memset (&sa, 0, sizeof sa);
387
388   i = sigfillset (&sa.sa_mask);
389   __go_assert (i == 0);
390
391   for (i = 0; runtime_sigtab[i].sig != -1; ++i)
392     {
393       if (runtime_sigtab[i].flags == 0)
394         continue;
395       if ((runtime_sigtab[i].flags & SigQueue) != queue)
396         continue;
397
398       if ((runtime_sigtab[i].flags & (SigCatch | SigQueue)) != 0)
399         {
400           if ((runtime_sigtab[i].flags & SigPanic) == 0)
401             {
402               sa.sa_flags = SA_ONSTACK;
403               sa.sa_handler = sig_tramp;
404             }
405           else
406             {
407 #ifdef SA_SIGINFO
408               sa.sa_flags = SA_SIGINFO;
409               sa.sa_sigaction = sig_panic_info_handler;
410 #else
411               sa.sa_flags = 0;
412               sa.sa_handler = sig_panic_handler;
413 #endif
414             }
415         }
416       else
417         {
418           sa.sa_flags = SA_ONSTACK;
419           sa.sa_handler = sig_ignore;
420         }
421
422       if ((runtime_sigtab[i].flags & SigRestart) != 0)
423         sa.sa_flags |= SA_RESTART;
424
425       if (sigaction (runtime_sigtab[i].sig, &sa, NULL) != 0)
426         __go_assert (0);
427     }
428 }
429
430 void
431 runtime_resetcpuprofiler(int32 hz)
432 {
433 #ifdef SIGPROF
434   struct itimerval it;
435   struct sigaction sa;
436   int i;
437
438   memset (&it, 0, sizeof it);
439
440   memset (&sa, 0, sizeof sa);
441   i = sigfillset (&sa.sa_mask);
442   __go_assert (i == 0);
443
444   if (hz == 0)
445     {
446       i = setitimer (ITIMER_PROF, &it, NULL);
447       __go_assert (i == 0);
448
449       sa.sa_handler = SIG_IGN;
450       i = sigaction (SIGPROF, &sa, NULL);
451       __go_assert (i == 0);
452     }
453   else
454     {
455       sa.sa_handler = sig_handler;
456       sa.sa_flags = SA_RESTART;
457       i = sigaction (SIGPROF, &sa, NULL);
458       __go_assert (i == 0);
459
460       it.it_interval.tv_sec = 0;
461       it.it_interval.tv_usec = 1000000 / hz;
462       it.it_value = it.it_interval;
463       i = setitimer (ITIMER_PROF, &it, NULL);
464       __go_assert (i == 0);
465     }
466 #endif
467
468   runtime_m()->profilehz = hz;
469 }
470
471 /* Used by the os package to raise SIGPIPE.  */
472
473 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
474
475 void
476 os_sigpipe (void)
477 {
478   struct sigaction sa;
479   int i;
480
481   memset (&sa, 0, sizeof sa);
482
483   sa.sa_handler = SIG_DFL;
484
485   i = sigemptyset (&sa.sa_mask);
486   __go_assert (i == 0);
487
488   if (sigaction (SIGPIPE, &sa, NULL) != 0)
489     abort ();
490
491   raise (SIGPIPE);
492 }