]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: make module typemaps visible to the GC
authorDavid Crawshaw <crawshaw@golang.org>
Mon, 31 Oct 2016 01:19:59 +0000 (21:19 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Mon, 31 Oct 2016 04:49:52 +0000 (04:49 +0000)
The map[typeOff]*_type object is created at run time and stored in
the moduledata. The moduledata object is marked by the linker as
SNOPTRDATA, so the reference is ignored by the GC. Running
misc/cgo/testplugin/test.bash with GOGC=1 will eventually collect
the typemap and crash.

This bug probably comes up in -linkshared binaries in Go 1.7.
I don't know why we haven't seen a report about this yet.

Fixes #17680

Change-Id: I0e9b5c006010e8edd51d9471651620ba665248d3
Reviewed-on: https://go-review.googlesource.com/32430
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Hudson-Doyle <michael.hudson@canonical.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/symtab.go
src/runtime/type.go

index 98b5f900e6b760c9baecca46357b7dee93b2b30c..d69f610ebb072ab40b6d3e806ff070a23a6dd6c2 100644 (file)
@@ -222,6 +222,15 @@ type modulehash struct {
        runtimehash  *string
 }
 
+// pinnedTypemaps are the map[typeOff]*_type from the moduledata objects.
+//
+// These typemap objects are allocated at run time on the heap, but the
+// only direct reference to them is in the moduledata, created by the
+// linker and marked SNOPTRDATA so it is ignored by the GC.
+//
+// To make sure the map isn't collected, we keep a second reference here.
+var pinnedTypemaps []map[typeOff]*_type
+
 var firstmoduledata moduledata  // linker symbol
 var lastmoduledatap *moduledata // linker symbol
 
index 7f7849d5a00d3d6a34564dac7d04c3e22af838a9..cacf880e9e2b0e7a3825c5809a3aaf7b3c55b06a 100644 (file)
@@ -497,7 +497,9 @@ func typelinksinit() {
                        // If any of this module's typelinks match a type from a
                        // prior module, prefer that prior type by adding the offset
                        // to this module's typemap.
-                       md.typemap = make(map[typeOff]*_type, len(md.typelinks))
+                       tm := make(map[typeOff]*_type, len(md.typelinks))
+                       pinnedTypemaps = append(pinnedTypemaps, tm)
+                       md.typemap = tm
                        for _, tl := range md.typelinks {
                                t := (*_type)(unsafe.Pointer(md.types + uintptr(tl)))
                                for _, candidate := range typehash[t.hash] {