]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: harden conditions when runtime panics on crash
authorDmitriy Vyukov <dvyukov@google.com>
Thu, 13 Mar 2014 09:25:59 +0000 (13:25 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Thu, 13 Mar 2014 09:25:59 +0000 (13:25 +0400)
This is especially important for SetPanicOnCrash,
but also useful for e.g. nil deref in mallocgc.
Panics on such crashes can't lead to anything useful,
only to deadlocks, hangs and obscure crashes.
This is a copy of broken but already LGTMed
https://golang.org/cl/68540043/

TBR=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/75320043

src/pkg/runtime/panic.c
src/pkg/runtime/runtime.h
src/pkg/runtime/signal_386.c
src/pkg/runtime/signal_amd64x.c
src/pkg/runtime/signal_arm.c

index 29bf7de27f23858b5b4a6dbba20d0407eb99082d..d35f7800a3281f7f6d84399ccbbd979e3ae4de4c 100644 (file)
@@ -485,6 +485,29 @@ runtime·throwinit(void)
        runtime·throw("recursive call during initialization - linker skew");
 }
 
+bool
+runtime·canpanic(G *gp)
+{
+       byte g;
+
+       USED(&g);  // don't use global g, it points to gsignal
+
+       // Is it okay for gp to panic instead of crashing the program?
+       // Yes, as long as it is running Go code, not runtime code,
+       // and not stuck in a system call.
+       if(gp == nil || gp != m->curg)
+               return false;
+       if(m->locks != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0)
+               return false;
+       if(gp->status != Grunning || gp->syscallsp != 0)
+               return false;
+#ifdef GOOS_windows
+       if(m->libcallsp != 0)
+               return false;
+#endif
+       return true;
+}
+
 void
 runtime·throw(int8 *s)
 {
index 0682a8026aa9e590e104a957ecac43c4c518d306..ecff533f59b2ee041c88821f61118085ca3c213b 100644 (file)
@@ -836,6 +836,7 @@ void        runtime·goenvs_unix(void);
 void*  runtime·getu(void);
 void   runtime·throw(int8*);
 void   runtime·panicstring(int8*);
+bool   runtime·canpanic(G*);
 void   runtime·prints(int8*);
 void   runtime·printf(int8*, ...);
 byte*  runtime·mchr(byte*, byte, byte*);
index 829f389cc27a0459c355daf133886dd8c34fb889..70790fa0a3ab804b0a02479702b4e2f3d47ea34d 100644 (file)
@@ -45,7 +45,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
 
        t = &runtime·sigtab[sig];
        if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               if(gp == nil || gp == m->g0)
+               if(!runtime·canpanic(gp))
                        goto Throw;
 
                // Make it look like a call to the signal func.
index 871891ad186d86fcd9a5a8f4bd9c98f5407b8c48..b21733871178863a353cd178dba37be87f472597 100644 (file)
@@ -54,7 +54,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
 
        t = &runtime·sigtab[sig];
        if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               if(gp == nil || gp == m->g0)
+               if(!runtime·canpanic(gp))
                        goto Throw;
 
                // Make it look like a call to the signal func.
index 563f1f2befdcf21f1a4fbcf0a24b863e232dc8ee..41997dbd85f8ff1ae7a62f9a7cce8db0737eb340 100644 (file)
@@ -52,7 +52,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
 
        t = &runtime·sigtab[sig];
        if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
-               if(gp == nil || gp == m->g0)
+               if(!runtime·canpanic(gp))
                        goto Throw;
 
                // Make it look like a call to the signal func.