summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/runtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/runtime.c')
-rw-r--r--src/pkg/runtime/runtime.c40
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