rs6000.c: Delete unnecessary forward declarations.
[official-gcc.git] / libgo / runtime / go-signal.c
blob5d398b04a02251d9184d9f5a3c63018616cef759
1 /* go-signal.c -- signal handling for Go.
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. */
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <sys/time.h>
12 #include "runtime.h"
13 #include "go-assert.h"
14 #include "go-panic.h"
16 #ifndef SA_RESTART
17 #define SA_RESTART 0
18 #endif
20 #ifdef USING_SPLIT_STACK
22 extern void __splitstack_getcontext(void *context[10]);
24 extern void __splitstack_setcontext(void *context[10]);
26 #endif
28 #define N SigNotify
29 #define K SigKill
30 #define T SigThrow
31 #define P SigPanic
32 #define D SigDefault
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. */
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 }
135 #undef N
136 #undef K
137 #undef T
138 #undef P
139 #undef D
141 /* Handle a signal, for cases where we don't panic. We can split the
142 stack here. */
144 static void
145 sig_handler (int sig)
147 int i;
149 #ifdef SIGPROF
150 if (sig == SIGPROF)
152 /* FIXME. */
153 runtime_sigprof (0, 0, nil, nil);
154 return;
156 #endif
158 for (i = 0; runtime_sigtab[i].sig != -1; ++i)
160 SigTab *t;
162 t = &runtime_sigtab[i];
164 if (t->sig != sig)
165 continue;
167 if ((t->flags & SigNotify) != 0)
169 if (__go_sigsend (sig))
170 return;
172 if ((t->flags & SigKill) != 0)
173 runtime_exit (2);
174 if ((t->flags & SigThrow) == 0)
175 return;
177 runtime_startpanic ();
180 const char *name = NULL;
182 #ifdef HAVE_STRSIGNAL
183 name = strsignal (sig);
184 #endif
186 if (name == NULL)
187 runtime_printf ("Signal %d\n", sig);
188 else
189 runtime_printf ("%s\n", name);
192 runtime_printf ("\n");
194 if (runtime_gotraceback ())
196 G *g;
198 g = runtime_g ();
199 runtime_traceback (g);
200 runtime_tracebackothers (g);
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. */
207 runtime_exit (2);
210 __builtin_unreachable ();
213 /* The start of handling a signal which panics. */
215 static void
216 sig_panic_leadin (int sig)
218 int i;
219 sigset_t clear;
221 if (runtime_m ()->mallocing)
223 runtime_printf ("caught signal while mallocing: %d\n", sig);
224 runtime_throw ("caught signal while mallocing");
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);
234 #ifdef SA_SIGINFO
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. */
240 static void
241 sig_panic_info_handler (int sig, siginfo_t *info,
242 void *context __attribute__ ((unused)))
244 G *g;
246 g = runtime_g ();
247 if (g == NULL || info->si_code == SI_USER)
249 sig_handler (sig);
250 return;
253 g->sig = sig;
254 g->sigcode0 = info->si_code;
255 g->sigcode1 = (uintptr_t) info->si_addr;
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. */
260 sig_panic_leadin (sig);
262 switch (sig)
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
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
285 #ifdef SIGFPE
286 case SIGFPE:
287 switch (info->si_code)
289 case FPE_INTDIV:
290 runtime_panicstring ("integer divide by zero");
291 case FPE_INTOVF:
292 runtime_panicstring ("integer overflow");
294 runtime_panicstring ("floating point error");
295 #endif
298 /* All signals with SigPanic should be in cases above, and this
299 handler should only be invoked for those signals. */
300 __builtin_unreachable ();
303 #else /* !defined (SA_SIGINFO) */
305 static void
306 sig_panic_handler (int sig)
308 G *g;
310 g = runtime_g ();
311 if (g == NULL)
313 sig_handler (sig);
314 return;
317 g->sig = sig;
318 g->sigcode0 = 0;
319 g->sigcode1 = 0;
321 sig_panic_leadin (sig);
323 switch (sig)
325 #ifdef SIGBUS
326 case SIGBUS:
327 runtime_panicstring ("invalid memory address or "
328 "nil pointer dereference");
329 #endif
331 #ifdef SIGSEGV
332 case SIGSEGV:
333 runtime_panicstring ("invalid memory address or "
334 "nil pointer dereference");
335 #endif
337 #ifdef SIGFPE
338 case SIGFPE:
339 runtime_panicstring ("integer divide by zero or floating point error");
340 #endif
343 /* All signals with SigPanic should be in cases above, and this
344 handler should only be invoked for those signals. */
345 __builtin_unreachable ();
348 #endif /* !defined (SA_SIGINFO) */
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. */
354 static void
355 sig_tramp (int) __attribute__ ((no_split_stack));
357 static void
358 sig_tramp (int sig)
360 G *gp;
361 M *mp;
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 ();
369 if (gp != NULL)
371 #ifdef USING_SPLIT_STACK
372 __splitstack_getcontext (&gp->stack_context[0]);
373 #endif
376 if (gp != NULL && mp->gsignal != NULL)
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
385 sig_handler (sig);
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. */
392 if (gp != NULL)
394 #ifdef USING_SPLIT_STACK
395 __splitstack_setcontext (&gp->stack_context[0]);
396 #endif
400 void
401 runtime_setsig (int32 i, bool def __attribute__ ((unused)), bool restart)
403 struct sigaction sa;
404 int r;
405 SigTab *t;
407 memset (&sa, 0, sizeof sa);
409 r = sigfillset (&sa.sa_mask);
410 __go_assert (r == 0);
412 t = &runtime_sigtab[i];
414 if ((t->flags & SigPanic) == 0)
416 sa.sa_flags = SA_ONSTACK;
417 sa.sa_handler = sig_tramp;
419 else
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
430 if (restart)
431 sa.sa_flags |= SA_RESTART;
433 if (sigaction (t->sig, &sa, NULL) != 0)
434 __go_assert (0);
437 /* Used by the os package to raise SIGPIPE. */
439 void os_sigpipe (void) __asm__ ("os.sigpipe");
441 void
442 os_sigpipe (void)
444 struct sigaction sa;
445 int i;
447 memset (&sa, 0, sizeof sa);
449 sa.sa_handler = SIG_DFL;
451 i = sigemptyset (&sa.sa_mask);
452 __go_assert (i == 0);
454 if (sigaction (SIGPIPE, &sa, NULL) != 0)
455 abort ();
457 raise (SIGPIPE);
460 void
461 runtime_setprof(bool on)
463 USED(on);