summaryrefslogtreecommitdiffstats
path: root/libgo/runtime
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-13 22:32:32 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-13 22:32:32 +0000
commiteae8641f08ed9258b22a456dd9f8dd015ec3c773 (patch)
treeedb990ae62544f8946086fcb5d2d72dbfffacef9 /libgo/runtime
parent8e86290125c6b2ffa4c9417729497a3551f7aaae (diff)
downloadppe42-gcc-eae8641f08ed9258b22a456dd9f8dd015ec3c773.tar.gz
ppe42-gcc-eae8641f08ed9258b22a456dd9f8dd015ec3c773.zip
compiler, runtime: Fix unexpected GC interfering with closure passing.
The Go frontend passes closures through to functions using the functions __go_set_closure and __go_get_closure. The expectation is that there are no function calls between set_closure and get_closure. However, it turns out that there can be function calls if some of the function arguments require type conversion to an interface type. Converting to an interface type can allocate memory, and that can in turn trigger a garbage collection, and that can in turn call pool cleanup functions that may call __go_set_closure. So the called function can see the wrong closure value, which is bad. This patch fixes the memory allocation function to preserve the closure value across any possible garbage collection. A test case is the libgo database/sql check run with the environment variable GOGC set to 1. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_9-branch@213933 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgo/runtime')
-rw-r--r--libgo/runtime/malloc.goc7
1 files changed, 7 insertions, 0 deletions
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 7120457a5b7..37bbf5ef63a 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -79,6 +79,7 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
MSpan *s;
MLink *v;
bool incallback;
+ void *closure;
if(size == 0) {
// All 0-length allocations use this pointer.
@@ -90,6 +91,10 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
m = runtime_m();
g = runtime_g();
+ // We should not be called in between __go_set_closure and the
+ // actual function call, but cope with it if we are.
+ closure = g->closure;
+
incallback = false;
if(m->mcache == nil && g->ncgo > 0) {
// For gccgo this case can occur when a cgo or SWIG function
@@ -206,6 +211,8 @@ runtime_mallocgc(uintptr size, uintptr typ, uint32 flag)
if(incallback)
runtime_entersyscall();
+ g->closure = closure;
+
return v;
}
OpenPOWER on IntegriCloud