Importing Upstream version 4.8.2
[platform/upstream/gcc48.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 #include "signal_unix.h"
16
17 #ifndef SA_RESTART
18   #define SA_RESTART 0
19 #endif
20
21 #ifdef USING_SPLIT_STACK
22
23 extern void __splitstack_getcontext(void *context[10]);
24
25 extern void __splitstack_setcontext(void *context[10]);
26
27 #endif
28
29 #define N SigNotify
30 #define K SigKill
31 #define T SigThrow
32 #define P SigPanic
33 #define D SigDefault
34
35 /* Signal actions.  This collects the sigtab tables for several
36    different targets from the master library.  SIGKILL, SIGCONT, and
37    SIGSTOP are not listed, as we don't want to set signal handlers for
38    them.  */
39
40 SigTab runtime_sigtab[] = {
41 #ifdef SIGHUP
42   { SIGHUP,     N + K },
43 #endif
44 #ifdef SIGINT
45   { SIGINT,     N + K },
46 #endif
47 #ifdef SIGQUIT
48   { SIGQUIT,    N + T },
49 #endif
50 #ifdef SIGILL
51   { SIGILL,     T },
52 #endif
53 #ifdef SIGTRAP
54   { SIGTRAP,    T },
55 #endif
56 #ifdef SIGABRT
57   { SIGABRT,    N + T },
58 #endif
59 #ifdef SIGBUS
60   { SIGBUS,     P },
61 #endif
62 #ifdef SIGFPE
63   { SIGFPE,     P },
64 #endif
65 #ifdef SIGUSR1
66   { SIGUSR1,    N },
67 #endif
68 #ifdef SIGSEGV
69   { SIGSEGV,    P },
70 #endif
71 #ifdef SIGUSR2
72   { SIGUSR2,    N },
73 #endif
74 #ifdef SIGPIPE
75   { SIGPIPE,    N },
76 #endif
77 #ifdef SIGALRM
78   { SIGALRM,    N },
79 #endif
80 #ifdef SIGTERM
81   { SIGTERM,    N + K },
82 #endif
83 #ifdef SIGSTKFLT
84   { SIGSTKFLT,  T },
85 #endif
86 #ifdef SIGCHLD
87   { SIGCHLD,    N },
88 #endif
89 #ifdef SIGTSTP
90   { SIGTSTP,    N + D },
91 #endif
92 #ifdef SIGTTIN
93   { SIGTTIN,    N + D },
94 #endif
95 #ifdef SIGTTOU
96   { SIGTTOU,    N + D },
97 #endif
98 #ifdef SIGURG
99   { SIGURG,     N },
100 #endif
101 #ifdef SIGXCPU
102   { SIGXCPU,    N },
103 #endif
104 #ifdef SIGXFSZ
105   { SIGXFSZ,    N },
106 #endif
107 #ifdef SIGVTALRM
108   { SIGVTALRM,  N },
109 #endif
110 #ifdef SIGPROF
111   { SIGPROF,    N },
112 #endif
113 #ifdef SIGWINCH
114   { SIGWINCH,   N },
115 #endif
116 #ifdef SIGIO
117   { SIGIO,      N },
118 #endif
119 #ifdef SIGPWR
120   { SIGPWR,     N },
121 #endif
122 #ifdef SIGSYS
123   { SIGSYS,     N },
124 #endif
125 #ifdef SIGEMT
126   { SIGEMT,     T },
127 #endif
128 #ifdef SIGINFO
129   { SIGINFO,    N },
130 #endif
131 #ifdef SIGTHR
132   { SIGTHR,     N },
133 #endif
134   { -1,         0 }
135 };
136 #undef N
137 #undef K
138 #undef T
139 #undef P
140 #undef D
141
142
143 static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
144
145 static void
146 runtime_badsignal(int32 sig)
147 {
148         // Avoid -D_FORTIFY_SOURCE problems.
149         int rv __attribute__((unused));
150
151         if (sig == SIGPROF) {
152                 return;  // Ignore SIGPROFs intended for a non-Go thread.
153         }
154         rv = runtime_write(2, badsignal, sizeof badsignal - 1);
155         runtime_exit(1);
156 }
157
158 /* Handle a signal, for cases where we don't panic.  We can split the
159    stack here.  */
160
161 void
162 runtime_sighandler (int sig, Siginfo *info,
163                     void *context __attribute__ ((unused)), G *gp)
164 {
165   M *m;
166   int i;
167
168   m = runtime_m ();
169
170 #ifdef SIGPROF
171   if (sig == SIGPROF)
172     {
173       if (m != NULL && gp != m->g0 && gp != m->gsignal)
174         runtime_sigprof ();
175       return;
176     }
177 #endif
178
179   if (m == NULL)
180     {
181       runtime_badsignal (sig);
182       return;
183     }
184
185   for (i = 0; runtime_sigtab[i].sig != -1; ++i)
186     {
187       SigTab *t;
188       bool notify, crash;
189
190       t = &runtime_sigtab[i];
191
192       if (t->sig != sig)
193         continue;
194
195       notify = false;
196 #ifdef SA_SIGINFO
197       notify = info != NULL && info->si_code == SI_USER;
198 #endif
199       if (notify || (t->flags & SigNotify) != 0)
200         {
201           if (__go_sigsend (sig))
202             return;
203         }
204       if ((t->flags & SigKill) != 0)
205         runtime_exit (2);
206       if ((t->flags & SigThrow) == 0)
207         return;
208
209       runtime_startpanic ();
210
211       {
212         const char *name = NULL;
213
214 #ifdef HAVE_STRSIGNAL
215         name = strsignal (sig);
216 #endif
217
218         if (name == NULL)
219           runtime_printf ("Signal %d\n", sig);
220         else
221           runtime_printf ("%s\n", name);
222       }
223
224       if (m->lockedg != NULL && m->ncgo > 0 && gp == m->g0)
225         {
226           runtime_printf("signal arrived during cgo execution\n");
227           gp = m->lockedg;
228         }
229
230       runtime_printf ("\n");
231
232       if (runtime_gotraceback (&crash))
233         {
234           G *g;
235
236           g = runtime_g ();
237           runtime_traceback (g);
238           runtime_tracebackothers (g);
239
240           /* The gc library calls runtime_dumpregs here, and provides
241              a function that prints the registers saved in context in
242              a readable form.  */
243         }
244
245       if (crash)
246         runtime_crash ();
247
248       runtime_exit (2);
249     }
250
251   __builtin_unreachable ();
252 }
253
254 /* The start of handling a signal which panics.  */
255
256 static void
257 sig_panic_leadin (int sig)
258 {
259   int i;
260   sigset_t clear;
261
262   if (runtime_m ()->mallocing)
263     {
264       runtime_printf ("caught signal while mallocing: %d\n", sig);
265       runtime_throw ("caught signal while mallocing");
266     }
267
268   /* The signal handler blocked signals; unblock them.  */
269   i = sigfillset (&clear);
270   __go_assert (i == 0);
271   i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
272   __go_assert (i == 0);
273 }
274
275 #ifdef SA_SIGINFO
276
277 /* Signal dispatch for signals which panic, on systems which support
278    SA_SIGINFO.  This is called on the thread stack, and as such it is
279    permitted to split the stack.  */
280
281 static void
282 sig_panic_info_handler (int sig, Siginfo *info, void *context)
283 {
284   G *g;
285
286   g = runtime_g ();
287   if (g == NULL || info->si_code == SI_USER)
288     {
289       runtime_sighandler (sig, info, context, g);
290       return;
291     }
292
293   g->sig = sig;
294   g->sigcode0 = info->si_code;
295   g->sigcode1 = (uintptr_t) info->si_addr;
296
297   /* It would be nice to set g->sigpc here as the gc library does, but
298      I don't know how to get it portably.  */
299
300   sig_panic_leadin (sig);
301
302   switch (sig)
303     {
304 #ifdef SIGBUS
305     case SIGBUS:
306       if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
307         runtime_panicstring ("invalid memory address or "
308                              "nil pointer dereference");
309       runtime_printf ("unexpected fault address %p\n", info->si_addr);
310       runtime_throw ("fault");
311 #endif
312
313 #ifdef SIGSEGV
314     case SIGSEGV:
315       if ((info->si_code == 0
316            || info->si_code == SEGV_MAPERR
317            || info->si_code == SEGV_ACCERR)
318           && (uintptr_t) info->si_addr < 0x1000)
319         runtime_panicstring ("invalid memory address or "
320                              "nil pointer dereference");
321       runtime_printf ("unexpected fault address %p\n", info->si_addr);
322       runtime_throw ("fault");
323 #endif
324
325 #ifdef SIGFPE
326     case SIGFPE:
327       switch (info->si_code)
328         {
329         case FPE_INTDIV:
330           runtime_panicstring ("integer divide by zero");
331         case FPE_INTOVF:
332           runtime_panicstring ("integer overflow");
333         }
334       runtime_panicstring ("floating point error");
335 #endif
336     }
337
338   /* All signals with SigPanic should be in cases above, and this
339      handler should only be invoked for those signals.  */
340   __builtin_unreachable ();
341 }
342
343 #else /* !defined (SA_SIGINFO) */
344
345 static void
346 sig_panic_handler (int sig)
347 {
348   G *g;
349
350   g = runtime_g ();
351   if (g == NULL)
352     {
353       runtime_sighandler (sig, NULL, NULL, g);
354       return;
355     }
356
357   g->sig = sig;
358   g->sigcode0 = 0;
359   g->sigcode1 = 0;
360
361   sig_panic_leadin (sig);
362
363   switch (sig)
364     {
365 #ifdef SIGBUS
366     case SIGBUS:
367       runtime_panicstring ("invalid memory address or "
368                            "nil pointer dereference");
369 #endif
370
371 #ifdef SIGSEGV
372     case SIGSEGV:
373       runtime_panicstring ("invalid memory address or "
374                            "nil pointer dereference");
375 #endif
376
377 #ifdef SIGFPE
378     case SIGFPE:
379       runtime_panicstring ("integer divide by zero or floating point error");
380 #endif
381     }
382
383   /* All signals with SigPanic should be in cases above, and this
384      handler should only be invoked for those signals.  */
385   __builtin_unreachable ();
386 }
387
388 #endif /* !defined (SA_SIGINFO) */
389
390 /* A signal handler used for signals which are not going to panic.
391    This is called on the alternate signal stack so it may not split
392    the stack.  */
393
394 static void
395 sig_tramp_info (int, Siginfo *, void *) __attribute__ ((no_split_stack));
396
397 static void
398 sig_tramp_info (int sig, Siginfo *info, void *context)
399 {
400   G *gp;
401   M *mp;
402
403   /* We are now running on the stack registered via sigaltstack.
404      (Actually there is a small span of time between runtime_siginit
405      and sigaltstack when the program starts.)  */
406   gp = runtime_g ();
407   mp = runtime_m ();
408
409   if (gp != NULL)
410     {
411 #ifdef USING_SPLIT_STACK
412       __splitstack_getcontext (&gp->stack_context[0]);
413 #endif
414     }
415
416   if (gp != NULL && mp->gsignal != NULL)
417     {
418       /* We are running on the signal stack.  Set the split stack
419          context so that the stack guards are checked correctly.  */
420 #ifdef USING_SPLIT_STACK
421       __splitstack_setcontext (&mp->gsignal->stack_context[0]);
422 #endif
423     }
424
425   runtime_sighandler (sig, info, context, gp);
426
427   /* We are going to return back to the signal trampoline and then to
428      whatever we were doing before we got the signal.  Restore the
429      split stack context so that stack guards are checked
430      correctly.  */
431
432   if (gp != NULL)
433     {
434 #ifdef USING_SPLIT_STACK
435       __splitstack_setcontext (&gp->stack_context[0]);
436 #endif
437     }
438 }
439
440 #ifndef SA_SIGINFO
441
442 static void sig_tramp (int sig) __attribute__ ((no_split_stack));
443
444 static void
445 sig_tramp (int sig)
446 {
447   sig_tramp_info (sig, NULL, NULL);
448 }
449
450 #endif
451
452 void
453 runtime_setsig (int32 i, GoSighandler *fn, bool restart)
454 {
455   struct sigaction sa;
456   int r;
457   SigTab *t;
458
459   memset (&sa, 0, sizeof sa);
460
461   r = sigfillset (&sa.sa_mask);
462   __go_assert (r == 0);
463
464   t = &runtime_sigtab[i];
465
466   if ((t->flags & SigPanic) == 0)
467     {
468 #ifdef SA_SIGINFO
469       sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
470       if (fn == runtime_sighandler)
471         fn = (void *) sig_tramp_info;
472       sa.sa_sigaction = (void *) fn;
473 #else
474       sa.sa_flags = SA_ONSTACK;
475       if (fn == runtime_sighandler)
476         fn = (void *) sig_tramp;
477       sa.sa_handler = (void *) fn;
478 #endif
479     }
480   else
481     {
482 #ifdef SA_SIGINFO
483       sa.sa_flags = SA_SIGINFO;
484       if (fn == runtime_sighandler)
485         fn = (void *) sig_panic_info_handler;
486       sa.sa_sigaction = (void *) fn;
487 #else
488       sa.sa_flags = 0;
489       if (fn == runtime_sighandler)
490         fn = (void *) sig_panic_handler;
491       sa.sa_handler = (void *) fn;
492 #endif
493     }
494
495   if (restart)
496     sa.sa_flags |= SA_RESTART;
497
498   if (sigaction (t->sig, &sa, NULL) != 0)
499     __go_assert (0);
500 }
501
502 GoSighandler*
503 runtime_getsig (int32 i)
504 {
505   struct sigaction sa;
506   int r;
507   SigTab *t;
508
509   memset (&sa, 0, sizeof sa);
510
511   r = sigemptyset (&sa.sa_mask);
512   __go_assert (r == 0);
513
514   t = &runtime_sigtab[i];
515
516   if (sigaction (t->sig, NULL, &sa) != 0)
517     runtime_throw ("sigaction read failure");
518
519   if ((void *) sa.sa_handler == sig_tramp_info)
520     return runtime_sighandler;
521 #ifdef SA_SIGINFO
522   if ((void *) sa.sa_handler == sig_panic_info_handler)
523     return runtime_sighandler;
524 #else
525   if ((void *) sa.sa_handler == sig_tramp
526       || (void *) sa.sa_handler == sig_panic_handler)
527     return runtime_sighandler;
528 #endif
529
530   return (void *) sa.sa_handler;
531 }
532
533 /* Used by the os package to raise SIGPIPE.  */
534
535 void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe");
536
537 void
538 os_sigpipe (void)
539 {
540   struct sigaction sa;
541   int i;
542
543   memset (&sa, 0, sizeof sa);
544
545   sa.sa_handler = SIG_DFL;
546
547   i = sigemptyset (&sa.sa_mask);
548   __go_assert (i == 0);
549
550   if (sigaction (SIGPIPE, &sa, NULL) != 0)
551     abort ();
552
553   raise (SIGPIPE);
554 }
555
556 void
557 runtime_setprof(bool on)
558 {
559         USED(on);
560 }