From: Dmitriy Vyukov Date: Thu, 27 Jun 2013 20:49:53 +0000 (+0400) Subject: runtime: fix goroutine status corruption X-Git-Tag: go1.2rc2~1151 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4eb17ecd1f1c5d130a0fe5c6bbd03714d315c41a;p=gostls13.git runtime: fix goroutine status corruption runtime.entersyscall() sets g->status = Gsyscall, then calls runtime.lock() which causes stack split. runtime.newstack() resets g->status to Grunning. This will lead to crash during GC (world is not stopped) or GC will scan stack incorrectly. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/10696043 --- diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c index 9dba008b13..5480c46970 100644 --- a/src/pkg/runtime/stack.c +++ b/src/pkg/runtime/stack.c @@ -138,6 +138,7 @@ runtime·oldstack(void) uintptr *src, *dst, *dstend; G *gp; int64 goid; + int32 oldstatus; gp = m->curg; top = (Stktop*)gp->stackbase; @@ -149,6 +150,10 @@ runtime·oldstack(void) runtime·printf("runtime: oldstack gobuf={pc:%p sp:%p lr:%p} cret=%p argsize=%p\n", top->gobuf.pc, top->gobuf.sp, top->gobuf.lr, m->cret, (uintptr)argsize); } + + // gp->status is usually Grunning, but it could be Gsyscall if a stack split + // happens during a function call inside entersyscall. + oldstatus = gp->status; gp->sched = top->gobuf; gp->sched.ret = m->cret; @@ -174,7 +179,7 @@ runtime·oldstack(void) if(top->free != 0) runtime·stackfree(old, top->free); - gp->status = Grunning; + gp->status = oldstatus; runtime·gogo(&gp->sched); } @@ -186,7 +191,7 @@ runtime·oldstack(void) void runtime·newstack(void) { - int32 framesize, argsize; + int32 framesize, argsize, oldstatus; Stktop *top; byte *stk; uintptr sp; @@ -196,9 +201,13 @@ runtime·newstack(void) bool reflectcall; uintptr free; + // gp->status is usually Grunning, but it could be Gsyscall if a stack split + // happens during a function call inside entersyscall. + gp = m->curg; + oldstatus = gp->status; + framesize = m->moreframesize; argsize = m->moreargsize; - gp = m->curg; gp->status = Gwaiting; gp->waitreason = "stack split"; reflectcall = framesize==1; @@ -304,7 +313,7 @@ runtime·newstack(void) runtime·gostartcall(&label, (void(*)(void))gp->sched.pc, gp->sched.ctxt); gp->sched.ctxt = nil; } - gp->status = Grunning; + gp->status = oldstatus; runtime·gogo(&label); *(int32*)345 = 123; // never return