From fbe9724cc368a76c8bb04c822a9877b9096758e6 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 30 Nov 2016 02:09:24 +0000 Subject: [PATCH] runtime: fixes for -buildmode=c-archive With -buildmode=c-archive, initsig is called before the memory allocator has been initialized. The code was doing a memory allocation because of the call to funcPC(sigtramp). When escape analysis is fully implemented, that call should not allocate. For now, finesse the issue by calling a C function to get the C function pointer value of sigtramp. When returning from a call from C to a Go function, a deferred function is run to go back to syscall mode. When the call occurs on a non-Go thread, that call sets g to nil, making it impossible to add the _defer struct back to the pool. Just drop it and let the garbage collector clean it up. Reviewed-on: https://go-review.googlesource.com/33675 From-SVN: r242992 --- gcc/go/gofrontend/MERGE | 2 +- libgo/go/runtime/panic.go | 9 +++++++++ libgo/go/runtime/signal1_unix.go | 6 +++--- libgo/go/runtime/stubs.go | 4 ++-- libgo/runtime/go-signal.c | 9 +++++++++ 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index fec65b8ca0d..ead134c5fe3 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -4d8e00e730897cc7e73b1582522ecab031cfcaf2 +1d3e0ceee45012a1c3b4ff7f5119a72f90bfcf6a The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/libgo/go/runtime/panic.go b/libgo/go/runtime/panic.go index 29a2f021d99..0ad178f45f6 100644 --- a/libgo/go/runtime/panic.go +++ b/libgo/go/runtime/panic.go @@ -141,6 +141,15 @@ func freedefer(d *_defer) { if d.special { return } + + // When C code calls a Go function on a non-Go thread, the + // deferred call to cgocallBackDone will set g to nil. + // Don't crash trying to put d on the free list; just let it + // be garbage collected. + if getg() == nil { + return + } + mp := acquirem() pp := mp.p.ptr() if len(pp.deferpool) == cap(pp.deferpool) { diff --git a/libgo/go/runtime/signal1_unix.go b/libgo/go/runtime/signal1_unix.go index f9327651911..d21bf4c31d7 100644 --- a/libgo/go/runtime/signal1_unix.go +++ b/libgo/go/runtime/signal1_unix.go @@ -93,7 +93,7 @@ func initsig(preinit bool) { } t.flags |= _SigHandling - setsig(i, funcPC(sigtramp), true) + setsig(i, getSigtramp(), true) } } @@ -137,7 +137,7 @@ func sigenable(sig uint32) { if t.flags&_SigHandling == 0 { t.flags |= _SigHandling fwdSig[sig] = getsig(int32(sig)) - setsig(int32(sig), funcPC(sigtramp), true) + setsig(int32(sig), getSigtramp(), true) } } } @@ -265,7 +265,7 @@ func raisebadsignal(sig int32, c *sigctxt) { // We may receive another instance of the signal before we // restore the Go handler, but that is not so bad: we know // that the Go program has been ignoring the signal. - setsig(sig, funcPC(sigtramp), true) + setsig(sig, getSigtramp(), true) } func crash() { diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go index 3bf8bb74bad..b2f1829fece 100644 --- a/libgo/go/runtime/stubs.go +++ b/libgo/go/runtime/stubs.go @@ -502,8 +502,8 @@ func goexit1() func schedtrace(bool) func freezetheworld() -// Signal trampoline, written in C. -func sigtramp() +// Get signal trampoline, written in C. +func getSigtramp() uintptr // The sa_handler field is generally hidden in a union, so use C accessors. func getSigactionHandler(*_sigaction) uintptr diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c index c1f1a52d201..711f71e8731 100644 --- a/libgo/runtime/go-signal.c +++ b/libgo/runtime/go-signal.c @@ -140,6 +140,15 @@ sigtramp(int sig, siginfo_t *info, void *context) #endif // USING_SPLIT_STACK +// C function to return the address of the sigtramp function. +uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp"); + +uintptr +getSigtramp() +{ + return (uintptr)(void*)sigtramp; +} + // C code to manage the sigaction sa_sigaction field, which is // typically a union and so hard for mksysinfo.sh to handle. -- 2.30.2