]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix goroutine status corruption
authorDmitriy Vyukov <dvyukov@google.com>
Thu, 27 Jun 2013 20:49:53 +0000 (00:49 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Thu, 27 Jun 2013 20:49:53 +0000 (00:49 +0400)
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

src/pkg/runtime/stack.c

index 9dba008b13b82b4c9a3c13890e1e70da5cefcfca..5480c4697059e5be53ddc6b7e1bcb3e13adf8168 100644 (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