diff mbox

libgo patch committed: Avoid GC crash with callbacks in new thread

Message ID CAOyqgcU-CDQh+LPJPEZVQMhaHE1Q8kT+ahAoP2+Er5EAzOXPLg@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Dec. 13, 2014, 12:52 a.m. UTC
There is a private program that crashes when using gccgo in a rather
complex scenario.  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.

This patch implements that.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian
diff mbox

Patch

diff -r 1bed87327b5c libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Wed Dec 10 12:35:39 2014 -0800
+++ b/libgo/runtime/proc.c	Fri Dec 12 16:24:41 2014 -0800
@@ -1150,6 +1150,7 @@ 
 	__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_setmg(nil, nil);
 
 	mp->curg->status = Gdead;
+	mp->curg->gcstack = nil;
+	mp->curg->gcnext_sp = nil;
 
 	mnext = lockextra(true);
 	mp->schedlink = mnext;