Commit b0a29f39 authored by Russ Cox's avatar Russ Cox

runtime: cgo-related fixes

* Separate internal and external LockOSThread, for cgo safety.
* Show goroutine that made faulting cgo call.
* Never start a panic due to a signal caused by a cgo call.

Fixes #3774.
Fixes #3775.
Fixes #3797.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/7228081
parent 32a6097f
...@@ -34,5 +34,6 @@ func TestPrintf(t *testing.T) { testPrintf(t) } ...@@ -34,5 +34,6 @@ func TestPrintf(t *testing.T) { testPrintf(t) }
func Test4029(t *testing.T) { test4029(t) } func Test4029(t *testing.T) { test4029(t) }
func TestBoolAlign(t *testing.T) { testBoolAlign(t) } func TestBoolAlign(t *testing.T) { testBoolAlign(t) }
func Test3729(t *testing.T) { test3729(t) } func Test3729(t *testing.T) { test3729(t) }
func Test3775(t *testing.T) { test3775(t) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
package cgotest
/*
void lockOSThreadCallback(void);
inline static void lockOSThreadC(void)
{
lockOSThreadCallback();
}
int usleep(unsigned usec);
*/
import "C"
import (
"runtime"
"testing"
)
func test3775(t *testing.T) {
// Used to panic because of the UnlockOSThread below.
C.lockOSThreadC()
}
//export lockOSThreadCallback
func lockOSThreadCallback() {
runtime.LockOSThread()
runtime.UnlockOSThread()
go C.usleep(10000)
runtime.Gosched()
}
...@@ -91,7 +91,6 @@ static int64 cgosync; /* represents possible synchronization in C code */ ...@@ -91,7 +91,6 @@ static int64 cgosync; /* represents possible synchronization in C code */
void *cgo_load_gm; /* filled in by dynamic linker when Cgo is available */ void *cgo_load_gm; /* filled in by dynamic linker when Cgo is available */
void *cgo_save_gm; /* filled in by dynamic linker when Cgo is available */ void *cgo_save_gm; /* filled in by dynamic linker when Cgo is available */
static void unlockm(void);
static void unwindm(void); static void unwindm(void);
// Call from Go to C. // Call from Go to C.
...@@ -119,22 +118,16 @@ runtime·cgocall(void (*fn)(void*), void *arg) ...@@ -119,22 +118,16 @@ runtime·cgocall(void (*fn)(void*), void *arg)
/* /*
* Lock g to m to ensure we stay on the same stack if we do a * Lock g to m to ensure we stay on the same stack if we do a
* cgo callback. * cgo callback. Add entry to defer stack in case of panic.
*/ */
d.special = false; runtime·lockOSThread();
if(m->lockedg == nil) { d.fn = (byte*)runtime·unlockOSThread;
m->lockedg = g; d.siz = 0;
g->lockedm = m; d.link = g->defer;
d.argp = (void*)-1; // unused because unlockm never recovers
// Add entry to defer stack in case of panic. d.special = true;
d.fn = (byte*)unlockm; d.free = false;
d.siz = 0; g->defer = &d;
d.link = g->defer;
d.argp = (void*)-1; // unused because unlockm never recovers
d.special = true;
d.free = false;
g->defer = &d;
}
m->ncgo++; m->ncgo++;
...@@ -161,24 +154,15 @@ runtime·cgocall(void (*fn)(void*), void *arg) ...@@ -161,24 +154,15 @@ runtime·cgocall(void (*fn)(void*), void *arg)
m->cgomal = nil; m->cgomal = nil;
} }
if(d.special) { if(g->defer != &d || d.fn != (byte*)runtime·unlockOSThread)
if(g->defer != &d || d.fn != (byte*)unlockm) runtime·throw("runtime: bad defer entry in cgocallback");
runtime·throw("runtime: bad defer entry in cgocallback"); g->defer = d.link;
g->defer = d.link; runtime·unlockOSThread();
unlockm();
}
if(raceenabled) if(raceenabled)
runtime·raceacquire(&cgosync); runtime·raceacquire(&cgosync);
} }
static void
unlockm(void)
{
m->lockedg = nil;
g->lockedm = nil;
}
void void
runtime·NumCgoCall(int64 ret) runtime·NumCgoCall(int64 ret)
{ {
......
...@@ -79,7 +79,6 @@ struct Sched { ...@@ -79,7 +79,6 @@ struct Sched {
int32 profilehz; // cpu profiling rate int32 profilehz; // cpu profiling rate
bool init; // running initialization bool init; // running initialization
bool lockmain; // init called runtime.LockOSThread
Note stopped; // one g can set waitstop and wait here for m's to stop Note stopped; // one g can set waitstop and wait here for m's to stop
}; };
...@@ -238,7 +237,7 @@ runtime·main(void) ...@@ -238,7 +237,7 @@ runtime·main(void)
// Those can arrange for main.main to run in the main thread // Those can arrange for main.main to run in the main thread
// by calling runtime.LockOSThread during initialization // by calling runtime.LockOSThread during initialization
// to preserve the lock. // to preserve the lock.
runtime·LockOSThread(); runtime·lockOSThread();
// From now on, newgoroutines may use non-main threads. // From now on, newgoroutines may use non-main threads.
setmcpumax(runtime·gomaxprocs); setmcpumax(runtime·gomaxprocs);
runtime·sched.init = true; runtime·sched.init = true;
...@@ -246,8 +245,7 @@ runtime·main(void) ...@@ -246,8 +245,7 @@ runtime·main(void)
scvg->issystem = true; scvg->issystem = true;
main·init(); main·init();
runtime·sched.init = false; runtime·sched.init = false;
if(!runtime·sched.lockmain) runtime·unlockOSThread();
runtime·UnlockOSThread();
// The deadlock detection has false negatives. // The deadlock detection has false negatives.
// Let scvg start up, to eliminate the false negative // Let scvg start up, to eliminate the false negative
...@@ -917,6 +915,7 @@ schedule(G *gp) ...@@ -917,6 +915,7 @@ schedule(G *gp)
if(gp->lockedm) { if(gp->lockedm) {
gp->lockedm = nil; gp->lockedm = nil;
m->lockedg = nil; m->lockedg = nil;
m->locked = 0;
} }
gp->idlem = nil; gp->idlem = nil;
runtime·unwindstack(gp, nil); runtime·unwindstack(gp, nil);
...@@ -1460,26 +1459,50 @@ runtime·gomaxprocsfunc(int32 n) ...@@ -1460,26 +1459,50 @@ runtime·gomaxprocsfunc(int32 n)
return ret; return ret;
} }
void static void
runtime·LockOSThread(void) LockOSThread(void)
{ {
if(m == &runtime·m0 && runtime·sched.init) {
runtime·sched.lockmain = true;
return;
}
m->lockedg = g; m->lockedg = g;
g->lockedm = m; g->lockedm = m;
} }
void void
runtime·UnlockOSThread(void) runtime·LockOSThread(void)
{
m->locked |= LockExternal;
LockOSThread();
}
void
runtime·lockOSThread(void)
{
m->locked += LockInternal;
LockOSThread();
}
static void
UnlockOSThread(void)
{ {
if(m == &runtime·m0 && runtime·sched.init) { if(m->locked != 0)
runtime·sched.lockmain = false;
return; return;
}
m->lockedg = nil; m->lockedg = nil;
g->lockedm = nil; g->lockedm = nil;
}
void
runtime·UnlockOSThread(void)
{
m->locked &= ~LockExternal;
UnlockOSThread();
}
void
runtime·unlockOSThread(void)
{
if(m->locked < LockInternal)
runtime·throw("runtime: internal error: misuse of lockOSThread/unlockOSThread");
m->locked -= LockInternal;
UnlockOSThread();
} }
bool bool
......
...@@ -281,6 +281,7 @@ struct M ...@@ -281,6 +281,7 @@ struct M
uint32 freglo[16]; // D[i] lsb and F[i] uint32 freglo[16]; // D[i] lsb and F[i]
uint32 freghi[16]; // D[i] msb and F[i+16] uint32 freghi[16]; // D[i] msb and F[i+16]
uint32 fflag; // floating point compare flags uint32 fflag; // floating point compare flags
uint32 locked; // tracking for LockOSThread
M* nextwaitm; // next M waiting for lock M* nextwaitm; // next M waiting for lock
uintptr waitsema; // semaphore for parking on locks uintptr waitsema; // semaphore for parking on locks
uint32 waitsemacount; uint32 waitsemacount;
...@@ -303,6 +304,15 @@ struct M ...@@ -303,6 +304,15 @@ struct M
uintptr end[]; uintptr end[];
}; };
// The m->locked word holds a single bit saying whether
// external calls to LockOSThread are in effect, and then a counter
// of the internal nesting depth of lockOSThread / unlockOSThread.
enum
{
LockExternal = 1,
LockInternal = 2,
};
struct Stktop struct Stktop
{ {
// The offsets of these fields are known to (hard-coded in) libmach. // The offsets of these fields are known to (hard-coded in) libmach.
...@@ -858,8 +868,8 @@ void runtime·semrelease(uint32*); ...@@ -858,8 +868,8 @@ void runtime·semrelease(uint32*);
int32 runtime·gomaxprocsfunc(int32 n); int32 runtime·gomaxprocsfunc(int32 n);
void runtime·procyield(uint32); void runtime·procyield(uint32);
void runtime·osyield(void); void runtime·osyield(void);
void runtime·LockOSThread(void); void runtime·lockOSThread(void);
void runtime·UnlockOSThread(void); void runtime·unlockOSThread(void);
void runtime·mapassign(MapType*, Hmap*, byte*, byte*); void runtime·mapassign(MapType*, Hmap*, byte*, byte*);
void runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*); void runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);
......
...@@ -47,7 +47,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -47,7 +47,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Work around Leopard bug that doesn't set FPE_INTDIV. // Work around Leopard bug that doesn't set FPE_INTDIV.
// Look at instruction to see if it is a divide. // Look at instruction to see if it is a divide.
...@@ -101,7 +101,11 @@ Throw: ...@@ -101,7 +101,11 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
} }
runtime·printf("pc: %x\n", r->eip); runtime·printf("PC=%x\n", r->eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -55,7 +55,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -55,7 +55,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Work around Leopard bug that doesn't set FPE_INTDIV. // Work around Leopard bug that doesn't set FPE_INTDIV.
// Look at instruction to see if it is a divide. // Look at instruction to see if it is a divide.
...@@ -111,7 +111,11 @@ Throw: ...@@ -111,7 +111,11 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
} }
runtime·printf("pc: %X\n", r->rip); runtime·printf("PC=%X\n", r->rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -54,7 +54,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -54,7 +54,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -97,6 +97,10 @@ Throw: ...@@ -97,6 +97,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", r->mc_eip); runtime·printf("PC=%X\n", r->mc_eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -62,7 +62,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -62,7 +62,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -105,6 +105,10 @@ Throw: ...@@ -105,6 +105,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", r->mc_rip); runtime·printf("PC=%X\n", r->mc_rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -75,7 +75,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -75,7 +75,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -118,6 +118,10 @@ Throw: ...@@ -118,6 +118,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%x\n", r->r15); runtime·printf("PC=%x\n", r->r15);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -50,7 +50,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -50,7 +50,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -93,6 +93,10 @@ Throw: ...@@ -93,6 +93,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", r->eip); runtime·printf("PC=%X\n", r->eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -60,7 +60,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -60,7 +60,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -103,6 +103,10 @@ Throw: ...@@ -103,6 +103,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", r->rip); runtime·printf("PC=%X\n", r->rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -57,7 +57,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -57,7 +57,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -101,6 +101,10 @@ Throw: ...@@ -101,6 +101,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%x\n", r->arm_pc); runtime·printf("PC=%x\n", r->arm_pc);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -53,7 +53,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -53,7 +53,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->_code != SI_USER && (t->flags & SigPanic)) { if(info->_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// We need to pass arguments out of band since // We need to pass arguments out of band since
...@@ -96,6 +96,10 @@ Throw: ...@@ -96,6 +96,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", mc->__gregs[REG_EIP]); runtime·printf("PC=%X\n", mc->__gregs[REG_EIP]);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -61,7 +61,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -61,7 +61,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->_code != SI_USER && (t->flags & SigPanic)) { if(info->_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// We need to pass arguments out of band since augmenting the // We need to pass arguments out of band since augmenting the
...@@ -103,6 +103,10 @@ Throw: ...@@ -103,6 +103,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", mc->__gregs[REG_RIP]); runtime·printf("PC=%X\n", mc->__gregs[REG_RIP]);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -50,7 +50,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -50,7 +50,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -93,6 +93,10 @@ Throw: ...@@ -93,6 +93,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", r->sc_eip); runtime·printf("PC=%X\n", r->sc_eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -59,7 +59,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) ...@@ -59,7 +59,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
t = &runtime·sigtab[sig]; t = &runtime·sigtab[sig];
if(info->si_code != SI_USER && (t->flags & SigPanic)) { if(info->si_code != SI_USER && (t->flags & SigPanic)) {
if(gp == nil) if(gp == nil || gp == m->g0)
goto Throw; goto Throw;
// Make it look like a call to the signal func. // Make it look like a call to the signal func.
// Have to pass arguments out of band since // Have to pass arguments out of band since
...@@ -102,6 +102,10 @@ Throw: ...@@ -102,6 +102,10 @@ Throw:
runtime·printf("%s\n", runtime·sigtab[sig].name); runtime·printf("%s\n", runtime·sigtab[sig].name);
runtime·printf("PC=%X\n", r->sc_rip); runtime·printf("PC=%X\n", r->sc_rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -68,6 +68,10 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) ...@@ -68,6 +68,10 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
info->ExceptionInformation[0], info->ExceptionInformation[1]); info->ExceptionInformation[0], info->ExceptionInformation[1]);
runtime·printf("PC=%x\n", r->Eip); runtime·printf("PC=%x\n", r->Eip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -75,6 +75,10 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) ...@@ -75,6 +75,10 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp)
info->ExceptionInformation[0], info->ExceptionInformation[1]); info->ExceptionInformation[0], info->ExceptionInformation[1]);
runtime·printf("PC=%X\n", r->Rip); runtime·printf("PC=%X\n", r->Rip);
if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = m->lockedg;
}
runtime·printf("\n"); runtime·printf("\n");
if(runtime·gotraceback()){ if(runtime·gotraceback()){
......
...@@ -202,6 +202,12 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr ...@@ -202,6 +202,12 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
void void
runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp) runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp)
{ {
if(gp->status == Gsyscall) {
// Override signal registers if blocked in system call.
pc0 = gp->sched.pc;
sp = (byte*)gp->sched.sp;
lr = nil;
}
runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100); runtime·gentraceback(pc0, sp, lr, gp, 0, nil, 100);
} }
......
...@@ -207,6 +207,11 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr ...@@ -207,6 +207,11 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
void void
runtime·traceback(byte *pc0, byte *sp, byte*, G *gp) runtime·traceback(byte *pc0, byte *sp, byte*, G *gp)
{ {
if(gp->status == Gsyscall) {
// Override signal registers if blocked in system call.
pc0 = gp->sched.pc;
sp = (byte*)gp->sched.sp;
}
runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100); runtime·gentraceback(pc0, sp, nil, gp, 0, nil, 100);
} }
......
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