runtime: correct a logic error in hashmap growth.
[gcc.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 }