]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: for c-archive/c-shared, install signal handlers synchronously
authorIan Lance Taylor <iant@golang.org>
Sat, 26 Dec 2015 17:51:59 +0000 (09:51 -0800)
committerIan Lance Taylor <iant@golang.org>
Sat, 9 Jan 2016 00:58:38 +0000 (00:58 +0000)
The previous behaviour of installing the signal handlers in a separate
thread meant that Go initialization raced with non-Go initialization if
the non-Go initialization also wanted to install signal handlers.  Make
installing signal handlers synchronous so that the process-wide behavior
is predictable.

Update #9896.

Change-Id: Ice24299877ec46f8518b072a381932d273096a32
Reviewed-on: https://go-review.googlesource.com/18150
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
23 files changed:
misc/cgo/testcarchive/main.c
src/os/signal/doc.go
src/runtime/os1_darwin.go
src/runtime/os1_dragonfly.go
src/runtime/os1_freebsd.go
src/runtime/os1_linux.go
src/runtime/os1_nacl.go
src/runtime/os1_netbsd.go
src/runtime/os1_openbsd.go
src/runtime/os1_plan9.go
src/runtime/os3_solaris.go
src/runtime/proc.go
src/runtime/rt0_darwin_386.s
src/runtime/rt0_darwin_amd64.s
src/runtime/rt0_darwin_arm.s
src/runtime/rt0_darwin_arm64.s
src/runtime/rt0_linux_386.s
src/runtime/rt0_linux_amd64.s
src/runtime/rt0_linux_arm.s
src/runtime/rt0_linux_arm64.s
src/runtime/signal1_unix.go
src/runtime/signal2_unix.go
src/runtime/signal_windows.go

index cc3170de89a21ec89a97e95692493720f280b69b..a90138f898a0f7eefe76727804a31a98a512dd2c 100644 (file)
@@ -2,15 +2,44 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "p.h"
 #include "libgo.h"
 
+static void (*oldHandler)(int, siginfo_t*, void*);
+
+static void handler(int signo, siginfo_t* info, void* ctxt) {
+       if (oldHandler) {
+               oldHandler(signo, info, ctxt);
+       }
+}
+
 int main(void) {
+       struct sigaction sa;
+       struct sigaction osa;
        int32_t res;
 
+       // Install our own signal handler.
+       memset(&sa, 0, sizeof sa);
+       sa.sa_sigaction = handler;
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+       memset(&osa, 0, sizeof osa);
+       sigemptyset(&osa.sa_mask);
+       if (sigaction(SIGSEGV, &sa, &osa) < 0) {
+               perror("sigaction");
+               return 2;
+       }
+       if (osa.sa_handler == SIG_DFL || (osa.sa_flags&SA_ONSTACK) == 0) {
+               fprintf(stderr, "Go runtime did not install signal handler\n");
+               return 2;
+       }
+       oldHandler = osa.sa_sigaction;
+
        if (!DidInitRun()) {
                fprintf(stderr, "ERROR: buildmode=c-archive init should run\n");
                return 2;
@@ -21,6 +50,16 @@ int main(void) {
                return 2;
        }
 
+       // Make sure our signal handler is still the one in use.
+       if (sigaction(SIGSEGV, NULL, &sa) < 0) {
+               perror("sigaction check");
+               return 2;
+       }
+       if (sa.sa_sigaction != handler) {
+               fprintf(stderr, "ERROR: wrong signal handler: %p != %p\n", sa.sa_sigaction, handler);
+               return 2;
+       }
+
        res = FromPkg();
        if (res != 1024) {
                fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res);
index f90492985feccd439fc64c3322df66cc8f824a6d..80e66cffe530de0954e73f6ab0314d19d481cc8f 100644 (file)
@@ -172,7 +172,10 @@ When Go code is built with options like -buildmode=c-shared, it will
 be run as part of an existing non-Go program. The non-Go code may
 have already installed signal handlers when the Go code starts (that
 may also happen in unusual cases when using cgo or SWIG; in that case,
-the discussion here applies).
+the discussion here applies).  For -buildmode=c-archive the Go runtime
+will initialize signals at global constructor time.  For
+-buildmode=c-shared the Go runtime will initialize signals when the
+shared library is loaded.
 
 If the Go runtime sees an existing signal handler for the SIGCANCEL or
 SIGSETXID signals (which are used only on GNU/Linux), it will turn on
index d34af6b216751473999109c58bb5a27eaa76f5bc..b5a1f5911950fd326607e3917322d97c828b436d 100644 (file)
@@ -125,6 +125,15 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer, fnarg uintptr) {
 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
 
+// Called to do synchronous initialization of Go code built with
+// -buildmode=c-archive or -buildmode=c-shared.
+// None of the Go runtime is initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func libpreinit() {
+       initsig(true)
+}
+
 // Called to initialize a new m (including the bootstrap m).
 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
 func mpreinit(mp *m) {
@@ -459,6 +468,8 @@ func memlimit() uintptr {
        return 0
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
        sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -471,6 +482,8 @@ func setsig(i int32, fn uintptr, restart bool) {
        sigaction(uint32(i), &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        var osa usigactiont
        sigaction(uint32(i), nil, &osa)
@@ -486,6 +499,8 @@ func setsigstack(i int32) {
        sigaction(uint32(i), &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa usigactiont
        sigaction(uint32(i), nil, &sa)
@@ -505,6 +520,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
        s := sigset(m[0])
        sigprocmask(_SIG_SETMASK, &s, nil)
index 5f0f00cb3cb5f8203449c87862e71cb5c4509358..59ffb809d3f40d5534917b61fd91090f1f54f17f 100644 (file)
@@ -213,6 +213,8 @@ type sigactiont struct {
        sa_mask      sigset
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
        sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -227,10 +229,14 @@ func setsig(i int32, fn uintptr, restart bool) {
        sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa sigactiont
        sigaction(i, nil, &sa)
@@ -253,6 +259,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
        var mask sigset
        copy(mask.__bits[:], m[:])
index 52e8dcbc83477f19b6e7bb45a54cb9e5e7c894e2..05d13439b8a648f65ef65bbb78008070a30c77ab 100644 (file)
@@ -220,6 +220,8 @@ type sigactiont struct {
        sa_mask    sigset
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
        sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -234,10 +236,14 @@ func setsig(i int32, fn uintptr, restart bool) {
        sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa sigactiont
        sigaction(i, nil, &sa)
@@ -260,6 +266,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m [(_NSIG + 31) / 32]uint32) {
        var mask sigset
        copy(mask.__bits[:], m[:])
index 961faddf100d0bb3aeb67f17284bff6a68b059ad..747a1ac5e373e31e5e078df1d388f279f3b1f644 100644 (file)
@@ -190,6 +190,15 @@ func goenvs() {
        goenvs_unix()
 }
 
+// Called to do synchronous initialization of Go code built with
+// -buildmode=c-archive or -buildmode=c-shared.
+// None of the Go runtime is initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func libpreinit() {
+       initsig(true)
+}
+
 // Called to initialize a new m (including the bootstrap m).
 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
 func mpreinit(mp *m) {
@@ -298,6 +307,8 @@ func memlimit() uintptr {
 func sigreturn()
 func sigtramp()
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
        memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
@@ -316,12 +327,11 @@ func setsig(i int32, fn uintptr, restart bool) {
                fn = funcPC(sigtramp)
        }
        sa.sa_handler = fn
-       // Qemu rejects rt_sigaction of SIGRTMAX (64).
-       if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 && i != 64 {
-               throw("rt_sigaction failure")
-       }
+       rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        var sa sigactiont
        if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
@@ -336,6 +346,8 @@ func setsigstack(i int32) {
        }
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa sigactiont
 
@@ -362,6 +374,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
        var mask sigset
        sigcopyset(&mask, m)
index c7212613697911fd076cf80285807ebb39de716c..3af51b7017156d815bc1390c019cd08c071ce6fa 100644 (file)
@@ -67,7 +67,7 @@ func goenvs() {
        goenvs_unix()
 }
 
-func initsig() {
+func initsig(preinit bool) {
 }
 
 //go:nosplit
index 2849b5aaf75cb181ca559eeb9582995e9b42bd55..79524aaf272f24615a89e157733c96e440fb4987 100644 (file)
@@ -206,6 +206,8 @@ type sigactiont struct {
        sa_flags     int32
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
        sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -220,10 +222,14 @@ func setsig(i int32, fn uintptr, restart bool) {
        sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa sigactiont
        sigaction(i, nil, &sa)
@@ -246,6 +252,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
        var mask sigset
        copy(mask.__bits[:], m[:])
index 24d847747d6695b3d29466020e2c6a1041ebfc32..7e1aa33f0b63cc262677bdc012d1f16c5db7b8d4 100644 (file)
@@ -220,6 +220,8 @@ type sigactiont struct {
        sa_flags     int32
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
        sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -234,10 +236,14 @@ func setsig(i int32, fn uintptr, restart bool) {
        sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa sigactiont
        sigaction(i, nil, &sa)
@@ -260,6 +266,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
        sigprocmask(_SIG_SETMASK, sigset(m[0]))
 }
index a75e956d17a43951b2aba83c012a8b184d4faaf8..61ebc1dc205784000d6017da6f50e32d902166ea 100644 (file)
@@ -107,7 +107,7 @@ func getRandomData(r []byte) {
 func goenvs() {
 }
 
-func initsig() {
+func initsig(preinit bool) {
 }
 
 //go:nosplit
index a112b2edd0d1761ec674a497f6532a3353acf53b..7d9ee5c00e9e9474468eeb5961a9a2bd82a8defb 100644 (file)
@@ -279,6 +279,8 @@ func memlimit() uintptr {
 
 func sigtramp()
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
        var sa sigactiont
 
@@ -295,6 +297,8 @@ func setsig(i int32, fn uintptr, restart bool) {
        sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
        var sa sigactiont
        sigaction(i, nil, &sa)
@@ -306,6 +310,8 @@ func setsigstack(i int32) {
        sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
        var sa sigactiont
        sigaction(i, nil, &sa)
@@ -328,6 +334,8 @@ func signalstack(s *stack) {
        sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
        var mask sigset
        copy(mask.__sigbits[:], m[:])
@@ -478,6 +486,8 @@ func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.P
        return int32(sysvicall4(&libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg)))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func raise(sig int32) /* int32 */ {
        sysvicall1(&libc_raise, uintptr(sig))
 }
@@ -516,6 +526,8 @@ func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ {
        sysvicall3(&libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue)))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ {
        sysvicall3(&libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact)))
 }
@@ -527,6 +539,7 @@ func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
 }
 
 //go:nosplit
+//go:nowritebarrierrec
 func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
        sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
 }
index 23429fd774adf040ed1a05c1a1914aabbd5bff04..b14aabde3dc6c600dbe4c6eb32a10a5d25cc0c8a 100644 (file)
@@ -1088,7 +1088,7 @@ func mstart1() {
                        cgoHasExtraM = true
                        newextram()
                }
-               initsig()
+               initsig(false)
        }
 
        if fn := _g_.m.mstartfn; fn != nil {
index be2e5640edd0b66d35ac63d5c33bba1d7bbf8f12..6b404db3a443df1dd0bbd15732e1f986033ecae1 100644 (file)
@@ -25,6 +25,10 @@ TEXT _rt0_386_darwin_lib(SB),NOSPLIT,$0
        MOVL    12(BP), AX
        MOVL    AX, _rt0_386_darwin_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVL    $runtime·libpreinit(SB), AX
+       CALL    AX
+
        SUBL    $12, SP
 
        // Create a new thread to do the runtime initialization and return.
index c4ebc88522861770b6059fe3bb93e9a19d059744..ad46fd406dc208f9522c1eb39ded4072162a7892 100644 (file)
@@ -23,6 +23,10 @@ TEXT _rt0_amd64_darwin_lib(SB),NOSPLIT,$0x48
        MOVQ    DI, _rt0_amd64_darwin_lib_argc<>(SB)
        MOVQ    SI, _rt0_amd64_darwin_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVQ    $runtime·libpreinit(SB), AX
+       CALL    AX
+
        // Create a new thread to do the runtime initialization and return.
        MOVQ    _cgo_sys_thread_create(SB), AX
        TESTQ   AX, AX
index d60985060d4a00f811984eee3fddef3e18832708..cbbea80ff885e66629556f697bb5fe442ad03b51 100644 (file)
@@ -25,6 +25,10 @@ TEXT _rt0_arm_darwin_lib(SB),NOSPLIT,$0
        MOVW  R0, _rt0_arm_darwin_lib_argc<>(SB)
        MOVW  R1, _rt0_arm_darwin_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVW    $runtime·libpreinit(SB), R3
+       CALL    (R3)
+
        // Create a new thread to do the runtime initialization and return.
        MOVW  _cgo_sys_thread_create(SB), R3
        CMP   $0, R3
index e4e4a30f4615b77791458b495642d477afdad73b..fa676c0abeadab83d04235dfb21176a51f866036 100644 (file)
@@ -25,6 +25,11 @@ TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$0
 
        MOVD  R0, _rt0_arm64_darwin_lib_argc<>(SB)
        MOVD  R1, _rt0_arm64_darwin_lib_argv<>(SB)
+
+       // Synchronous initialization.
+       MOVD    $runtime·libpreinit(SB), R4
+       BL      (R4)
+
        // Create a new thread to do the runtime initialization and return.
        MOVD  _cgo_sys_thread_create(SB), R4
        MOVD  $_rt0_arm64_darwin_lib_go(SB), R0
index 633e8069df519eec80da6b578790181d15b202cd..59a30b41e8bb9b58caf7b5e762929e866578bb42 100644 (file)
@@ -26,6 +26,10 @@ TEXT _rt0_386_linux_lib(SB),NOSPLIT,$0
        MOVL    12(BP), AX
        MOVL    AX, _rt0_386_linux_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVL    $runtime·libpreinit(SB), AX
+       CALL    AX
+
        SUBL    $8, SP
 
        // Create a new thread to do the runtime initialization.
index 726b550d3568dfb36fd18f7a8dbcf95f020de3ea..564b51c0b3ccc811301da183d53c84015fad5688 100644 (file)
@@ -23,6 +23,10 @@ TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x48
        MOVQ    DI, _rt0_amd64_linux_lib_argc<>(SB)
        MOVQ    SI, _rt0_amd64_linux_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVQ    $runtime·libpreinit(SB), AX
+       CALL    AX
+
        // Create a new thread to do the runtime initialization and return.
        MOVQ    _cgo_sys_thread_create(SB), AX
        TESTQ   AX, AX
index b71a3f926789ad13e9ebae2498daab61a9ff307e..d28c15a43af0aab4ab9c94f48cab74b9e6d455b4 100644 (file)
@@ -26,6 +26,10 @@ TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$32
        MOVW    R0, _rt0_arm_linux_lib_argc<>(SB)
        MOVW    R1, _rt0_arm_linux_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVW    $runtime·libpreinit(SB), R2
+       CALL    (R2)
+
        // Create a new thread to do the runtime initialization.
        MOVW    _cgo_sys_thread_create(SB), R2
        CMP     $0, R2
index 4027527168b38e4461234866b3d7f5808d20f415..2b32e352099dfa78c6289ec78344274343bc9848 100644 (file)
@@ -20,6 +20,10 @@ TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$40
        MOVD    R0, _rt0_arm64_linux_lib_argc<>(SB)
        MOVD    R1, _rt0_arm64_linux_lib_argv<>(SB)
 
+       // Synchronous initialization.
+       MOVD    $runtime·libpreinit(SB), R4
+       BL      (R4)
+
        // Create a new thread to do the runtime initialization and return.
        MOVD    _cgo_sys_thread_create(SB), R4
        CMP     $0, R4
index 19f37d970904e0296ad708a945f0d55d06430564..abb9639d9671831b120f61348c8b8cb55bdeb5e0 100644 (file)
@@ -34,15 +34,33 @@ var (
        maskUpdatedChan chan struct{}
 )
 
-func initsig() {
+func init() {
        // _NSIG is the number of signals on this operating system.
        // sigtable should describe what to do for all the possible signals.
        if len(sigtable) != _NSIG {
                print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
-               throw("initsig")
+               throw("bad sigtable len")
+       }
+}
+
+var signalsOK bool
+
+// Initialize signals.
+// Called by libpreinit so runtime may not be initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func initsig(preinit bool) {
+       if !preinit {
+               // It's now OK for signal handlers to run.
+               signalsOK = true
+       }
+
+       // For c-archive/c-shared this is called by libpreinit with
+       // preinit == true.
+       if (isarchive || islibrary) && !preinit {
+               return
        }
 
-       // First call: basic setup.
        for i := int32(0); i < _NSIG; i++ {
                t := &sigtable[i]
                if t.flags == 0 || t.flags&_SigDefault != 0 {
@@ -64,6 +82,8 @@ func initsig() {
        }
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func sigInstallGoHandler(sig int32) bool {
        // For some signals, we respect an inherited SIG_IGN handler
        // rather than insist on installing our own default handler.
@@ -101,6 +121,7 @@ func sigenable(sig uint32) {
                <-maskUpdatedChan
                if t.flags&_SigHandling == 0 {
                        t.flags |= _SigHandling
+                       fwdSig[sig] = getsig(int32(sig))
                        setsig(int32(sig), funcPC(sighandler), true)
                }
        }
@@ -163,6 +184,8 @@ func sigpipe() {
 // dieFromSignal kills the program with a signal.
 // This provides the expected exit status for the shell.
 // This is only called with fatal signals expected to kill the process.
+//go:nosplit
+//go:nowritebarrierrec
 func dieFromSignal(sig int32) {
        setsig(sig, _SIG_DFL, false)
        updatesigmask(sigmask{})
index 7481b8570ac24ecf294857ab533af8e81315fc7d..3fe625f83ccd224c49e26b2be7c6f4ce9fc26fa4 100644 (file)
@@ -22,6 +22,20 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
                return false
        }
        fwdFn := fwdSig[sig]
+
+       if !signalsOK {
+               // The only way we can get here is if we are in a
+               // library or archive, we installed a signal handler
+               // at program startup, but the Go runtime has not yet
+               // been initialized.
+               if fwdFn == _SIG_DFL {
+                       dieFromSignal(int32(sig))
+               } else {
+                       sigfwd(fwdFn, sig, info, ctx)
+               }
+               return true
+       }
+
        flags := sigtable[sig].flags
 
        // If there is no handler to forward to, no need to forward.
index 5cfa20fbfe26c988a6f4887f8e30836fa07637e9..ab7183fe6b5692d0e1ac94daf7f3296bee87cbb6 100644 (file)
@@ -191,7 +191,7 @@ func setBadSignalMsg() {
 
 // Following are not implemented.
 
-func initsig() {
+func initsig(preinit bool) {
 }
 
 func sigenable(sig uint32) {