]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix data race in stackalloc
authorDmitriy Vyukov <dvyukov@google.com>
Fri, 8 Aug 2014 16:13:57 +0000 (20:13 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Fri, 8 Aug 2014 16:13:57 +0000 (20:13 +0400)
Stack shrinking happens during mark phase,
and it assumes that it owns stackcache in mcache.
Stack cache flushing also happens during mark phase,
and it accesses stackcache's w/o any synchronization.
This leads to stackcache corruption:
http://goperfd.appspot.com/log/309af5571dfd7e1817259b9c9cf9bcf9b2c27610

LGTM=khr
R=khr
CC=golang-codereviews, rsc
https://golang.org/cl/126870043

src/pkg/runtime/stack.c

index 0a806e8fabbae9785652311d52775fb4fdcf4b59..772080af550c691b105055bd27ce957b2be25a85 100644 (file)
@@ -223,9 +223,11 @@ runtime·stackalloc(G *gp, uint32 n)
                        n2 >>= 1;
                }
                c = g->m->mcache;
-               if(c == nil) {
-                       // This can happen in the guts of exitsyscall or
+               if(c == nil || g->m->gcing || g->m->helpgc) {
+                       // c == nil can happen in the guts of exitsyscall or
                        // procresize. Just get a stack from the global pool.
+                       // Also don't touch stackcache during gc
+                       // as it's flushed concurrently.
                        runtime·lock(&stackpoolmu);
                        x = poolalloc(order);
                        runtime·unlock(&stackpoolmu);
@@ -285,7 +287,7 @@ runtime·stackfree(G *gp, void *v, Stktop *top)
                }
                x = (MLink*)v;
                c = g->m->mcache;
-               if(c == nil) {
+               if(c == nil || g->m->gcing || g->m->helpgc) {
                        runtime·lock(&stackpoolmu);
                        poolfree(x, order);
                        runtime·unlock(&stackpoolmu);