From fbe9724cc368a76c8bb04c822a9877b9096758e6 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor <ian@gcc.gnu.org>
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 fec65b8ca0dc..ead134c5fe30 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 29a2f021d993..0ad178f45f61 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 f9327651911a..d21bf4c31d7a 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 3bf8bb74bad9..b2f1829feced 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 c1f1a52d2014..711f71e8731b 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.
 
-- 
GitLab