OSDN Git Service

libgo: Update to weekly.2012-03-22.
[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 N SigNotify
29 #define K SigKill
30 #define T SigThrow
31 #define P SigPanic
32 #define D SigDefault
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,     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 }
134 };
135 #undef N
136 #undef K
137 #undef T
138 #undef P
139 #undef D
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       SigTab *t;
162
163       t = &runtime_sigtab[i];
164
165       if (t->sig != sig)
166         continue;
167
168       if ((t->flags & SigNotify) != 0)
169         {
170           if (__go_sigsend (sig))
171             return;
172         }
173       if ((t->flags & SigKill) != 0)
174         runtime_exit (2);
175       if ((t->flags & SigThrow) == 0)
176         return;
177
178       runtime_startpanic ();
179
180       /* We should do a stack backtrace here.  Until we can do that,
181          we reraise the signal in order to get a slightly better
182          report from the shell.  */
183
184       memset (&sa, 0, sizeof sa);
185
186       sa.sa_handler = SIG_DFL;
187
188       i = sigemptyset (&sa.sa_mask);
189       __go_assert (i == 0);
190
191       if (sigaction (sig, &sa, NULL) != 0)
192         abort ();
193
194       raise (sig);
195
196       runtime_exit (2);
197     }
198
199   __builtin_unreachable ();
200 }
201
202 /* The start of handling a signal which panics.  */
203
204 static void
205 sig_panic_leadin (int sig)
206 {
207   int i;
208   sigset_t clear;
209
210   if (runtime_m ()->mallocing)
211     {
212       runtime_printf ("caught signal while mallocing: %d\n", sig);
213       runtime_throw ("caught signal while mallocing");
214     }
215
216   /* The signal handler blocked signals; unblock them.  */
217   i = sigfillset (&clear);
218   __go_assert (i == 0);
219   i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
220   __go_assert (i == 0);
221 }
222
223 #ifdef SA_SIGINFO
224
225 /* Signal dispatch for signals which panic, on systems which support
226    SA_SIGINFO.  This is called on the thread stack, and as such it is
227    permitted to split the stack.  */
228
229 static void
230 sig_panic_info_handler (int sig, siginfo_t *info,
231                         void *context __attribute__ ((unused)))
232 {
233   if (runtime_g () == NULL || info->si_code == SI_USER)
234     {
235       sig_handler (sig);
236       return;
237     }
238
239   sig_panic_leadin (sig);
240
241   switch (sig)
242     {
243 #ifdef SIGBUS
244     case SIGBUS:
245       if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
246         runtime_panicstring ("invalid memory address or "
247                              "nil pointer dereference");
248       runtime_printf ("unexpected fault address %p\n", info->si_addr);
249       runtime_throw ("fault");
250 #endif
251
252 #ifdef SIGSEGV
253     case SIGSEGV:
254       if ((info->si_code == 0
255            || info->si_code == SEGV_MAPERR
256            || info->si_code == SEGV_ACCERR)
257           && (uintptr_t) info->si_addr < 0x1000)
258         runtime_panicstring ("invalid memory address or "
259                              "nil pointer dereference");
260       runtime_printf ("unexpected fault address %p\n", info->si_addr);
261       runtime_throw ("fault");
262 #endif
263
264 #ifdef SIGFPE
265     case SIGFPE:
266       switch (info->si_code)
267         {
268         case FPE_INTDIV:
269           runtime_panicstring ("integer divide by zero");
270         case FPE_INTOVF:
271           runtime_panicstring ("integer overflow");
272         }
273       runtime_panicstring ("floating point error");
274 #endif
275     }
276
277   /* All signals with SigPanic should be in cases above, and this
278      handler should only be invoked for those signals.  */
279   __builtin_unreachable ();
280 }
281
282 #else /* !defined (SA_SIGINFO) */
283
284 static void
285 sig_panic_handler (int sig)
286 {
287   if (runtime_g () == NULL)
288     {
289       sig_handler (sig);
290       return;
291     }
292
293   sig_panic_leadin (sig);
294
295   switch (sig)
296     {
297 #ifdef SIGBUS
298     case SIGBUS:
299       runtime_panicstring ("invalid memory address or "
300                            "nil pointer dereference");
301 #endif
302
303 #ifdef SIGSEGV
304     case SIGSEGV:
305       runtime_panicstring ("invalid memory address or "
306                            "nil pointer dereference");
307 #endif
308
309 #ifdef SIGFPE
310     case SIGFPE:
311       runtime_panicstring ("integer divide by zero or floating point error");
312 #endif
313     }
314
315   /* All signals with SigPanic should be in cases above, and this
316      handler should only be invoked for those signals.  */
317   __builtin_unreachable ();
318 }
319
320 #endif /* !defined (SA_SIGINFO) */
321
322 /* A signal handler used for signals which are not going to panic.
323    This is called on the alternate signal stack so it may not split
324    the stack.  */
325
326 static void
327 sig_tramp (int) __attribute__ ((no_split_stack));
328
329 static void
330 sig_tramp (int sig)
331 {
332   G *gp;
333   M *mp;
334
335   /* We are now running on the stack registered via sigaltstack.
336      (Actually there is a small span of time between runtime_siginit
337      and sigaltstack when the program starts.)  */
338   gp = runtime_g ();
339   mp = runtime_m ();
340
341   if (gp != NULL)
342     {
343 #ifdef USING_SPLIT_STACK
344       __splitstack_getcontext (&gp->stack_context[0]);
345 #endif
346     }
347
348   if (gp != NULL && mp->gsignal != NULL)
349     {
350       /* We are running on the signal stack.  Set the split stack
351          context so that the stack guards are checked correctly.  */
352 #ifdef USING_SPLIT_STACK
353       __splitstack_setcontext (&mp->gsignal->stack_context[0]);
354 #endif
355     }
356
357   sig_handler (sig);
358
359   /* We are going to return back to the signal trampoline and then to
360      whatever we were doing before we got the signal.  Restore the
361      split stack context so that stack guards are checked
362      correctly.  */
363
364   if (gp != NULL)
365     {
366 #ifdef USING_SPLIT_STACK
367       __splitstack_setcontext (&gp->stack_context[0]);
368 #endif
369     }
370 }
371
372 void
373 runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
374 {
375   struct sigaction sa;
376   int r;
377   SigTab *t;
378
379   memset (&sa, 0, sizeof sa);
380
381   r = sigfillset (&sa.sa_mask);
382   __go_assert (r == 0);
383
384   t = &runtime_sigtab[i];
385
386   if ((t->flags & SigPanic) == 0)
387     {
388       sa.sa_flags = SA_ONSTACK;
389       sa.sa_handler = sig_tramp;
390     }
391   else
392     {
393 #ifdef SA_SIGINFO
394       sa.sa_flags = SA_SIGINFO;
395       sa.sa_sigaction = sig_panic_info_handler;
396 #else
397       sa.sa_flags = 0;
398       sa.sa_handler = sig_panic_handler;
399 #endif
400     }
401
402   if (restart)
403     sa.sa_flags |= SA_RESTART;
404
405   if (sigaction (t->sig, &sa, NULL) != 0)
406     __go_assert (0);
407 }
408
409 /* Used by the os package to raise SIGPIPE.  */
410
411 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
412
413 void
414 os_sigpipe (void)
415 {
416   struct sigaction sa;
417   int i;
418
419   memset (&sa, 0, sizeof sa);
420
421   sa.sa_handler = SIG_DFL;
422
423   i = sigemptyset (&sa.sa_mask);
424   __go_assert (i == 0);
425
426   if (sigaction (SIGPIPE, &sa, NULL) != 0)
427     abort ();
428
429   raise (SIGPIPE);
430 }
431
432 void
433 runtime_setprof(bool on)
434 {
435         USED(on);
436 }