github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gofrontend/libgo/runtime/go-signal.c (about) 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 /* Handle a signal, for cases where we don't panic. We can split the 143 stack here. */ 144 145 void 146 runtime_sighandler (int sig, Siginfo *info, 147 void *context __attribute__ ((unused)), G *gp) 148 { 149 M *m; 150 int i; 151 152 m = runtime_m (); 153 154 #ifdef SIGPROF 155 if (sig == SIGPROF) 156 { 157 if (m != NULL && gp != m->g0 && gp != m->gsignal) 158 runtime_sigprof (); 159 return; 160 } 161 #endif 162 163 if (m == NULL) 164 { 165 runtime_badsignal (sig); 166 return; 167 } 168 169 for (i = 0; runtime_sigtab[i].sig != -1; ++i) 170 { 171 SigTab *t; 172 bool notify, crash; 173 174 t = &runtime_sigtab[i]; 175 176 if (t->sig != sig) 177 continue; 178 179 notify = false; 180 #ifdef SA_SIGINFO 181 notify = info != NULL && info->si_code == SI_USER; 182 #endif 183 if (notify || (t->flags & SigNotify) != 0) 184 { 185 if (__go_sigsend (sig)) 186 return; 187 } 188 if ((t->flags & SigKill) != 0) 189 runtime_exit (2); 190 if ((t->flags & SigThrow) == 0) 191 return; 192 193 runtime_startpanic (); 194 195 { 196 const char *name = NULL; 197 198 #ifdef HAVE_STRSIGNAL 199 name = strsignal (sig); 200 #endif 201 202 if (name == NULL) 203 runtime_printf ("Signal %d\n", sig); 204 else 205 runtime_printf ("%s\n", name); 206 } 207 208 if (m->lockedg != NULL && m->ncgo > 0 && gp == m->g0) 209 { 210 runtime_printf("signal arrived during cgo execution\n"); 211 gp = m->lockedg; 212 } 213 214 runtime_printf ("\n"); 215 216 if (runtime_gotraceback (&crash)) 217 { 218 G *g; 219 220 g = runtime_g (); 221 runtime_traceback (); 222 runtime_tracebackothers (g); 223 224 /* The gc library calls runtime_dumpregs here, and provides 225 a function that prints the registers saved in context in 226 a readable form. */ 227 } 228 229 if (crash) 230 runtime_crash (); 231 232 runtime_exit (2); 233 } 234 235 __builtin_unreachable (); 236 } 237 238 /* The start of handling a signal which panics. */ 239 240 static void 241 sig_panic_leadin (G *gp) 242 { 243 int i; 244 sigset_t clear; 245 246 if (!runtime_canpanic (gp)) 247 runtime_throw ("unexpected signal during runtime execution"); 248 249 /* The signal handler blocked signals; unblock them. */ 250 i = sigfillset (&clear); 251 __go_assert (i == 0); 252 i = pthread_sigmask (SIG_UNBLOCK, &clear, NULL); 253 __go_assert (i == 0); 254 } 255 256 #ifdef SA_SIGINFO 257 258 /* Signal dispatch for signals which panic, on systems which support 259 SA_SIGINFO. This is called on the thread stack, and as such it is 260 permitted to split the stack. */ 261 262 static void 263 sig_panic_info_handler (int sig, Siginfo *info, void *context) 264 { 265 G *g; 266 267 g = runtime_g (); 268 if (g == NULL || info->si_code == SI_USER) 269 { 270 runtime_sighandler (sig, info, context, g); 271 return; 272 } 273 274 g->sig = sig; 275 g->sigcode0 = info->si_code; 276 g->sigcode1 = (uintptr_t) info->si_addr; 277 278 /* It would be nice to set g->sigpc here as the gc library does, but 279 I don't know how to get it portably. */ 280 281 sig_panic_leadin (g); 282 283 switch (sig) 284 { 285 #ifdef SIGBUS 286 case SIGBUS: 287 if ((info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000) 288 || g->paniconfault) 289 runtime_panicstring ("invalid memory address or " 290 "nil pointer dereference"); 291 runtime_printf ("unexpected fault address %p\n", info->si_addr); 292 runtime_throw ("fault"); 293 #endif 294 295 #ifdef SIGSEGV 296 case SIGSEGV: 297 if (((info->si_code == 0 298 || info->si_code == SEGV_MAPERR 299 || info->si_code == SEGV_ACCERR) 300 && (uintptr_t) info->si_addr < 0x1000) 301 || g->paniconfault) 302 runtime_panicstring ("invalid memory address or " 303 "nil pointer dereference"); 304 runtime_printf ("unexpected fault address %p\n", info->si_addr); 305 runtime_throw ("fault"); 306 #endif 307 308 #ifdef SIGFPE 309 case SIGFPE: 310 switch (info->si_code) 311 { 312 case FPE_INTDIV: 313 runtime_panicstring ("integer divide by zero"); 314 case FPE_INTOVF: 315 runtime_panicstring ("integer overflow"); 316 } 317 runtime_panicstring ("floating point error"); 318 #endif 319 } 320 321 /* All signals with SigPanic should be in cases above, and this 322 handler should only be invoked for those signals. */ 323 __builtin_unreachable (); 324 } 325 326 #else /* !defined (SA_SIGINFO) */ 327 328 static void 329 sig_panic_handler (int sig) 330 { 331 G *g; 332 333 g = runtime_g (); 334 if (g == NULL) 335 { 336 runtime_sighandler (sig, NULL, NULL, g); 337 return; 338 } 339 340 g->sig = sig; 341 g->sigcode0 = 0; 342 g->sigcode1 = 0; 343 344 sig_panic_leadin (g); 345 346 switch (sig) 347 { 348 #ifdef SIGBUS 349 case SIGBUS: 350 runtime_panicstring ("invalid memory address or " 351 "nil pointer dereference"); 352 #endif 353 354 #ifdef SIGSEGV 355 case SIGSEGV: 356 runtime_panicstring ("invalid memory address or " 357 "nil pointer dereference"); 358 #endif 359 360 #ifdef SIGFPE 361 case SIGFPE: 362 runtime_panicstring ("integer divide by zero or floating point error"); 363 #endif 364 } 365 366 /* All signals with SigPanic should be in cases above, and this 367 handler should only be invoked for those signals. */ 368 __builtin_unreachable (); 369 } 370 371 #endif /* !defined (SA_SIGINFO) */ 372 373 /* A signal handler used for signals which are not going to panic. 374 This is called on the alternate signal stack so it may not split 375 the stack. */ 376 377 static void 378 sig_tramp_info (int, Siginfo *, void *) __attribute__ ((no_split_stack)); 379 380 static void 381 sig_tramp_info (int sig, Siginfo *info, void *context) 382 { 383 G *gp; 384 M *mp; 385 #ifdef USING_SPLIT_STACK 386 void *stack_context[10]; 387 #endif 388 389 /* We are now running on the stack registered via sigaltstack. 390 (Actually there is a small span of time between runtime_siginit 391 and sigaltstack when the program starts.) */ 392 gp = runtime_g (); 393 mp = runtime_m (); 394 395 if (gp != NULL) 396 { 397 #ifdef USING_SPLIT_STACK 398 __splitstack_getcontext (&stack_context[0]); 399 #endif 400 } 401 402 if (gp != NULL && mp->gsignal != NULL) 403 { 404 /* We are running on the signal stack. Set the split stack 405 context so that the stack guards are checked correctly. */ 406 #ifdef USING_SPLIT_STACK 407 __splitstack_setcontext (&mp->gsignal->stack_context[0]); 408 #endif 409 } 410 411 runtime_sighandler (sig, info, context, gp); 412 413 /* We are going to return back to the signal trampoline and then to 414 whatever we were doing before we got the signal. Restore the 415 split stack context so that stack guards are checked 416 correctly. */ 417 418 if (gp != NULL) 419 { 420 #ifdef USING_SPLIT_STACK 421 __splitstack_setcontext (&stack_context[0]); 422 #endif 423 } 424 } 425 426 #ifndef SA_SIGINFO 427 428 static void sig_tramp (int sig) __attribute__ ((no_split_stack)); 429 430 static void 431 sig_tramp (int sig) 432 { 433 sig_tramp_info (sig, NULL, NULL); 434 } 435 436 #endif 437 438 void 439 runtime_setsig (int32 i, GoSighandler *fn, bool restart) 440 { 441 struct sigaction sa; 442 int r; 443 SigTab *t; 444 445 memset (&sa, 0, sizeof sa); 446 447 r = sigfillset (&sa.sa_mask); 448 __go_assert (r == 0); 449 450 t = &runtime_sigtab[i]; 451 452 if ((t->flags & SigPanic) == 0) 453 { 454 #ifdef SA_SIGINFO 455 sa.sa_flags = SA_ONSTACK | SA_SIGINFO; 456 if (fn == runtime_sighandler) 457 fn = (void *) sig_tramp_info; 458 sa.sa_sigaction = (void *) fn; 459 #else 460 sa.sa_flags = SA_ONSTACK; 461 if (fn == runtime_sighandler) 462 fn = (void *) sig_tramp; 463 sa.sa_handler = (void *) fn; 464 #endif 465 } 466 else 467 { 468 #ifdef SA_SIGINFO 469 sa.sa_flags = SA_SIGINFO; 470 if (fn == runtime_sighandler) 471 fn = (void *) sig_panic_info_handler; 472 sa.sa_sigaction = (void *) fn; 473 #else 474 sa.sa_flags = 0; 475 if (fn == runtime_sighandler) 476 fn = (void *) sig_panic_handler; 477 sa.sa_handler = (void *) fn; 478 #endif 479 } 480 481 if (restart) 482 sa.sa_flags |= SA_RESTART; 483 484 if (sigaction (t->sig, &sa, NULL) != 0) 485 __go_assert (0); 486 } 487 488 GoSighandler* 489 runtime_getsig (int32 i) 490 { 491 struct sigaction sa; 492 int r; 493 SigTab *t; 494 495 memset (&sa, 0, sizeof sa); 496 497 r = sigemptyset (&sa.sa_mask); 498 __go_assert (r == 0); 499 500 t = &runtime_sigtab[i]; 501 502 if (sigaction (t->sig, NULL, &sa) != 0) 503 runtime_throw ("sigaction read failure"); 504 505 if ((void *) sa.sa_handler == sig_tramp_info) 506 return runtime_sighandler; 507 #ifdef SA_SIGINFO 508 if ((void *) sa.sa_handler == sig_panic_info_handler) 509 return runtime_sighandler; 510 #else 511 if ((void *) sa.sa_handler == sig_tramp 512 || (void *) sa.sa_handler == sig_panic_handler) 513 return runtime_sighandler; 514 #endif 515 516 return (void *) sa.sa_handler; 517 } 518 519 /* Used by the os package to raise SIGPIPE. */ 520 521 void os_sigpipe (void) __asm__ (GOSYM_PREFIX "os.sigpipe"); 522 523 void 524 os_sigpipe (void) 525 { 526 struct sigaction sa; 527 int i; 528 529 memset (&sa, 0, sizeof sa); 530 531 sa.sa_handler = SIG_DFL; 532 533 i = sigemptyset (&sa.sa_mask); 534 __go_assert (i == 0); 535 536 if (sigaction (SIGPIPE, &sa, NULL) != 0) 537 abort (); 538 539 raise (SIGPIPE); 540 } 541 542 void 543 runtime_setprof(bool on) 544 { 545 USED(on); 546 }