diff options
Diffstat (limited to 'src/pkg/runtime/runtime.c')
-rw-r--r-- | src/pkg/runtime/runtime.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c index e3a20d48a..1a3653f10 100644 --- a/src/pkg/runtime/runtime.c +++ b/src/pkg/runtime/runtime.c @@ -3,12 +3,13 @@ // license that can be found in the LICENSE file. #include "runtime.h" +#include "stack.h" enum { maxround = sizeof(uintptr), }; -int32 runtime·panicking = 0; +uint32 runtime·panicking; int32 runtime·gotraceback(void) @@ -21,14 +22,24 @@ runtime·gotraceback(void) return runtime·atoi(p); } +static Lock paniclk; + void -runtime·dopanic(int32 unused) +runtime·startpanic(void) { - if(runtime·panicking) { - runtime·printf("double panic\n"); + if(m->dying) { + runtime·printf("panic during panic\n"); runtime·exit(3); } - runtime·panicking++; + m->dying = 1; + runtime·xadd(&runtime·panicking, 1); + runtime·lock(&paniclk); +} + +void +runtime·dopanic(int32 unused) +{ + static bool didothers; if(g->sig != 0) runtime·printf("\n[signal %x code=%p addr=%p pc=%p]\n", @@ -37,10 +48,22 @@ runtime·dopanic(int32 unused) runtime·printf("\n"); if(runtime·gotraceback()){ runtime·traceback(runtime·getcallerpc(&unused), runtime·getcallersp(&unused), 0, g); - runtime·tracebackothers(g); + if(!didothers) { + didothers = true; + runtime·tracebackothers(g); + } } - - runtime·breakpoint(); // so we can grab it in a debugger + 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); + } + runtime·exit(2); } @@ -73,6 +96,7 @@ runtime·throwinit(void) void runtime·throw(int8 *s) { + runtime·startpanic(); runtime·printf("throw: %s\n", s); runtime·dopanic(0); *(int32*)0 = 0; // not reached |