runtime: Clear stack pointers for extra G's.
authorIan Lance Taylor <ian@gcc.gnu.org>
Sat, 13 Dec 2014 00:52:20 +0000 (00:52 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 13 Dec 2014 00:52:20 +0000 (00:52 +0000)
Fix an unusual C to Go callback case.  Newly created C threads
call into Go code, forcing the Go code to allocate new M and G
structures.  While executing Go code, the stack is split.  The
Go code then returns.  Returning from a Go callback is treated
as entering a system call, so the G gcstack field is set to
point to the Go stack.  In this case, though, we were called
from a newly created C thread, so we drop the extra M and G
structures.  The C thread then exits.

Then a new C thread calls into Go code, reusing the previously
created M and G.  The Go code requires a larger stack frame,
causing the old stack segment to be unmapped and a new stack
segment allocated.  At this point the gcstack field is
pointing to the old stack segment.

Then a garbage collection occurs.  The garbage collector sees
that the gcstack field is not nil, so it scans it as the first
stack segment.  Unfortunately it points to memory that was
unmapped.  So the program crashes.

The fix is simple: when handling extra G structures created
for callbacks from new C threads, clear the gcstack field.

From-SVN: r218699

libgo/runtime/proc.c

index 8907c3aa520d7b2e62579ec6e458b2015ea09593..03d1c1a271c0c341823b7e0bd794dd73b68ca6d9 100644 (file)
@@ -1150,6 +1150,7 @@ runtime_needm(void)
        __splitstack_getcontext(&g->stack_context[0]);
 #else
        g->gcinitial_sp = &mp;
+       g->gcstack = nil;
        g->gcstack_size = 0;
        g->gcnext_sp = &mp;
 #endif
@@ -1251,6 +1252,8 @@ runtime_dropm(void)
        runtime_setmg(nil, nil);
 
        mp->curg->status = Gdead;
+       mp->curg->gcstack = nil;
+       mp->curg->gcnext_sp = nil;
 
        mnext = lockextra(true);
        mp->schedlink = mnext;