Commit 15696287 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: harden conditions when runtime panics on crash

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
parent 5daffee1
...@@ -485,6 +485,29 @@ runtime·throwinit(void) ...@@ -485,6 +485,29 @@ runtime·throwinit(void)
runtime·throw("recursive call during initialization - linker skew"); 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 void
runtime·throw(int8 *s) runtime·throw(int8 *s)
{ {
......
...@@ -836,6 +836,7 @@ void runtime·goenvs_unix(void); ...@@ -836,6 +836,7 @@ void runtime·goenvs_unix(void);
void* runtime·getu(void); void* runtime·getu(void);
void runtime·throw(int8*); void runtime·throw(int8*);
void runtime·panicstring(int8*); void runtime·panicstring(int8*);
bool runtime·canpanic(G*);
void runtime·prints(int8*); void runtime·prints(int8*);
void runtime·printf(int8*, ...); void runtime·printf(int8*, ...);
byte* runtime·mchr(byte*, byte, byte*); byte* runtime·mchr(byte*, byte, byte*);
......
...@@ -45,7 +45,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) ...@@ -45,7 +45,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) { if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0) if(!runtime·canpanic(gp))
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
......
...@@ -54,7 +54,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) ...@@ -54,7 +54,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) { if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0) if(!runtime·canpanic(gp))
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
......
...@@ -52,7 +52,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp) ...@@ -52,7 +52,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *ctxt, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) { if(SIG_CODE0(info, ctxt) != SI_USER && (t->flags & SigPanic)) {
if(gp == nil || gp == m->g0) if(!runtime·canpanic(gp))
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment