aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/stack.c
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2013-06-28 00:49:53 +0400
committerDmitriy Vyukov <dvyukov@google.com>2013-06-28 00:49:53 +0400
commit4eb17ecd1f1c5d130a0fe5c6bbd03714d315c41a (patch)
tree40f08834154dfdf27ae778de613516dca623ec00 /src/pkg/runtime/stack.c
parentb92b09300a2b85d02041499f5cf93a7b30939c36 (diff)
downloadgo-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.c17
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