diff options
| author | Dmitriy Vyukov <dvyukov@google.com> | 2013-06-28 00:49:53 +0400 |
|---|---|---|
| committer | Dmitriy Vyukov <dvyukov@google.com> | 2013-06-28 00:49:53 +0400 |
| commit | 4eb17ecd1f1c5d130a0fe5c6bbd03714d315c41a (patch) | |
| tree | 40f08834154dfdf27ae778de613516dca623ec00 /src/pkg/runtime/stack.c | |
| parent | b92b09300a2b85d02041499f5cf93a7b30939c36 (diff) | |
| download | go-4eb17ecd1f1c5d130a0fe5c6bbd03714d315c41a.tar.xz | |
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
Diffstat (limited to 'src/pkg/runtime/stack.c')
| -rw-r--r-- | src/pkg/runtime/stack.c | 17 |
1 files changed, 13 insertions, 4 deletions
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 |
