aboutsummaryrefslogtreecommitdiff
path: root/src/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg')
-rw-r--r--src/pkg/runtime/panic.c23
-rw-r--r--src/pkg/runtime/runtime.h1
-rw-r--r--src/pkg/runtime/signal_386.c2
-rw-r--r--src/pkg/runtime/signal_amd64x.c2
-rw-r--r--src/pkg/runtime/signal_arm.c2
5 files changed, 27 insertions, 3 deletions
diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c
index 29bf7de27f..d35f7800a3 100644
--- a/src/pkg/runtime/panic.c
+++ b/src/pkg/runtime/panic.c
@@ -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)
{
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 0682a8026a..ecff533f59 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -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*);
diff --git a/src/pkg/runtime/signal_386.c b/src/pkg/runtime/signal_386.c
index 829f389cc2..70790fa0a3 100644
--- a/src/pkg/runtime/signal_386.c
+++ b/src/pkg/runtime/signal_386.c
@@ -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.
diff --git a/src/pkg/runtime/signal_amd64x.c b/src/pkg/runtime/signal_amd64x.c
index 871891ad18..b217338711 100644
--- a/src/pkg/runtime/signal_amd64x.c
+++ b/src/pkg/runtime/signal_amd64x.c
@@ -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.
diff --git a/src/pkg/runtime/signal_arm.c b/src/pkg/runtime/signal_arm.c
index 563f1f2bef..41997dbd85 100644
--- a/src/pkg/runtime/signal_arm.c
+++ b/src/pkg/runtime/signal_arm.c
@@ -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.