This patch to libgo fixes a couple of problems that arise when
building Go code into an archive or shared library that is linked into
a C program.

In archive mode, 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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 242726)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -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.
Index: libgo/go/runtime/panic.go
===================================================================
--- libgo/go/runtime/panic.go   (revision 242724)
+++ libgo/go/runtime/panic.go   (working copy)
@@ -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) {
Index: libgo/go/runtime/signal1_unix.go
===================================================================
--- libgo/go/runtime/signal1_unix.go    (revision 242724)
+++ libgo/go/runtime/signal1_unix.go    (working copy)
@@ -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 *sigctx
        // 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() {
Index: libgo/go/runtime/stubs.go
===================================================================
--- libgo/go/runtime/stubs.go   (revision 242724)
+++ libgo/go/runtime/stubs.go   (working copy)
@@ -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
Index: libgo/runtime/go-signal.c
===================================================================
--- libgo/runtime/go-signal.c   (revision 242724)
+++ libgo/runtime/go-signal.c   (working copy)
@@ -140,6 +140,15 @@ sigtramp(int sig, siginfo_t *info, void
 
 #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.
 

Reply via email to