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
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);
}
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);