1
0
mirror of https://github.com/golang/go synced 2024-11-26 15:36:59 -07:00

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
This commit is contained in:
Dmitriy Vyukov 2013-06-28 00:49:53 +04:00
parent b92b09300a
commit 4eb17ecd1f

View File

@ -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