void runtime_dopanic(int32 unused __attribute__ ((unused))) { G *g; static bool didothers; bool crash; int32 t; g = runtime_g(); if(g->sig != 0) runtime_printf("[signal %x code=%p addr=%p]\n", g->sig, (void*)g->sigcode0, (void*)g->sigcode1); if((t = runtime_gotraceback(&crash)) > 0){ if(g != runtime_m()->g0) { runtime_printf("\n"); runtime_goroutineheader(g); runtime_traceback(); runtime_printcreatedby(g); } else if(t >= 2 || runtime_m()->throwing > 0) { runtime_printf("\nruntime stack:\n"); runtime_traceback(); } if(!didothers) { didothers = true; runtime_tracebackothers(g); } } runtime_unlock(&paniclk); if(runtime_xadd(&runtime_panicking, -1) != 0) { // Some other m is panicking too. // Let it print what it needs to print. // Wait forever without chewing up cpu. // It will exit when it's done. static Lock deadlock; runtime_lock(&deadlock); runtime_lock(&deadlock); } if(crash) runtime_crash(); runtime_exit(2); }
static void sig_handler (int sig) { int i; if (runtime_m () == NULL) { runtime_badsignal (sig); return; } #ifdef SIGPROF if (sig == SIGPROF) { runtime_sigprof (); return; } #endif for (i = 0; runtime_sigtab[i].sig != -1; ++i) { SigTab *t; t = &runtime_sigtab[i]; if (t->sig != sig) continue; if ((t->flags & SigNotify) != 0) { if (__go_sigsend (sig)) return; } if ((t->flags & SigKill) != 0) runtime_exit (2); if ((t->flags & SigThrow) == 0) return; runtime_startpanic (); { const char *name = NULL; #ifdef HAVE_STRSIGNAL name = strsignal (sig); #endif if (name == NULL) runtime_printf ("Signal %d\n", sig); else runtime_printf ("%s\n", name); } runtime_printf ("\n"); if (runtime_gotraceback ()) { G *g; g = runtime_g (); runtime_traceback (g); runtime_tracebackothers (g); /* The gc library calls runtime_dumpregs here, and provides a function that prints the registers saved in context in a readable form. */ } runtime_exit (2); } __builtin_unreachable (); }