From c31fc2f424c31a4915c81500e8da72dc751d0db5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 13 Dec 2014 00:52:20 +0000 Subject: [PATCH] runtime: Clear stack pointers for extra G's. 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 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index 8907c3a..03d1c1a 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -1150,6 +1150,7 @@ runtime_needm(void) __splitstack_getcontext(&g->stack_context[0]); #else g->gcinitial_sp = ∓ + g->gcstack = nil; g->gcstack_size = 0; g->gcnext_sp = ∓ #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; -- 2.7.4