From f4c7a12c2c4b0aef99b4957a778736a4da9ae4ec Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Sun, 30 Oct 2016 21:19:59 -0400 Subject: [PATCH] runtime: make module typemaps visible to the GC 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 Reviewed-by: Michael Hudson-Doyle Reviewed-by: Ian Lance Taylor --- src/runtime/symtab.go | 9 +++++++++ src/runtime/type.go | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 98b5f900e6..d69f610ebb 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -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 diff --git a/src/runtime/type.go b/src/runtime/type.go index 7f7849d5a0..cacf880e9e 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -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] { -- 2.48.1