OSDN Git Service

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