1
0
mirror of https://github.com/golang/go synced 2024-11-12 02:10:21 -07:00

runtime: for c-archive/c-shared, install signal handlers synchronously

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>
This commit is contained in:
Ian Lance Taylor 2015-12-26 09:51:59 -08:00
parent 0b3807a2a3
commit 21b4f234c7
23 changed files with 200 additions and 12 deletions

View File

@ -2,15 +2,44 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include <signal.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "p.h" #include "p.h"
#include "libgo.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) { int main(void) {
struct sigaction sa;
struct sigaction osa;
int32_t res; 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()) { if (!DidInitRun()) {
fprintf(stderr, "ERROR: buildmode=c-archive init should run\n"); fprintf(stderr, "ERROR: buildmode=c-archive init should run\n");
return 2; return 2;
@ -21,6 +50,16 @@ int main(void) {
return 2; 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(); res = FromPkg();
if (res != 1024) { if (res != 1024) {
fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res); fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res);

View 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 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 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, 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 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 SIGSETXID signals (which are used only on GNU/Linux), it will turn on

View 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 failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
var failthreadcreate = []byte("runtime: failed to create 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 to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory. // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func mpreinit(mp *m) { func mpreinit(mp *m) {
@ -459,6 +468,8 @@ func memlimit() uintptr {
return 0 return 0
} }
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@ -471,6 +482,8 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(uint32(i), &sa, nil) sigaction(uint32(i), &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
var osa usigactiont var osa usigactiont
sigaction(uint32(i), nil, &osa) sigaction(uint32(i), nil, &osa)
@ -486,6 +499,8 @@ func setsigstack(i int32) {
sigaction(uint32(i), &sa, nil) sigaction(uint32(i), &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func getsig(i int32) uintptr { func getsig(i int32) uintptr {
var sa usigactiont var sa usigactiont
sigaction(uint32(i), nil, &sa) sigaction(uint32(i), nil, &sa)
@ -505,6 +520,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
s := sigset(m[0]) s := sigset(m[0])
sigprocmask(_SIG_SETMASK, &s, nil) sigprocmask(_SIG_SETMASK, &s, nil)

View File

@ -213,6 +213,8 @@ type sigactiont struct {
sa_mask sigset sa_mask sigset
} }
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@ -227,10 +229,14 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
throw("setsigstack") throw("setsigstack")
} }
//go:nosplit
//go:nowritebarrierrec
func getsig(i int32) uintptr { func getsig(i int32) uintptr {
var sa sigactiont var sa sigactiont
sigaction(i, nil, &sa) sigaction(i, nil, &sa)
@ -253,6 +259,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
var mask sigset var mask sigset
copy(mask.__bits[:], m[:]) copy(mask.__bits[:], m[:])

View File

@ -220,6 +220,8 @@ type sigactiont struct {
sa_mask sigset sa_mask sigset
} }
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@ -234,10 +236,14 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
throw("setsigstack") throw("setsigstack")
} }
//go:nosplit
//go:nowritebarrierrec
func getsig(i int32) uintptr { func getsig(i int32) uintptr {
var sa sigactiont var sa sigactiont
sigaction(i, nil, &sa) sigaction(i, nil, &sa)
@ -260,6 +266,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m [(_NSIG + 31) / 32]uint32) { func updatesigmask(m [(_NSIG + 31) / 32]uint32) {
var mask sigset var mask sigset
copy(mask.__bits[:], m[:]) copy(mask.__bits[:], m[:])

View File

@ -190,6 +190,15 @@ func goenvs() {
goenvs_unix() 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 to initialize a new m (including the bootstrap m).
// Called on the parent thread (main thread in case of bootstrap), can allocate memory. // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
func mpreinit(mp *m) { func mpreinit(mp *m) {
@ -298,6 +307,8 @@ func memlimit() uintptr {
func sigreturn() func sigreturn()
func sigtramp() func sigtramp()
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa)) memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
@ -316,12 +327,11 @@ func setsig(i int32, fn uintptr, restart bool) {
fn = funcPC(sigtramp) fn = funcPC(sigtramp)
} }
sa.sa_handler = fn sa.sa_handler = fn
// Qemu rejects rt_sigaction of SIGRTMAX (64). rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 && i != 64 {
throw("rt_sigaction failure")
}
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
var sa sigactiont var sa sigactiont
if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 { 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 { func getsig(i int32) uintptr {
var sa sigactiont var sa sigactiont
@ -362,6 +374,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
var mask sigset var mask sigset
sigcopyset(&mask, m) sigcopyset(&mask, m)

View File

@ -67,7 +67,7 @@ func goenvs() {
goenvs_unix() goenvs_unix()
} }
func initsig() { func initsig(preinit bool) {
} }
//go:nosplit //go:nosplit

View File

@ -206,6 +206,8 @@ type sigactiont struct {
sa_flags int32 sa_flags int32
} }
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@ -220,10 +222,14 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
throw("setsigstack") throw("setsigstack")
} }
//go:nosplit
//go:nowritebarrierrec
func getsig(i int32) uintptr { func getsig(i int32) uintptr {
var sa sigactiont var sa sigactiont
sigaction(i, nil, &sa) sigaction(i, nil, &sa)
@ -246,6 +252,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
var mask sigset var mask sigset
copy(mask.__bits[:], m[:]) copy(mask.__bits[:], m[:])

View File

@ -220,6 +220,8 @@ type sigactiont struct {
sa_flags int32 sa_flags int32
} }
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@ -234,10 +236,14 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
throw("setsigstack") throw("setsigstack")
} }
//go:nosplit
//go:nowritebarrierrec
func getsig(i int32) uintptr { func getsig(i int32) uintptr {
var sa sigactiont var sa sigactiont
sigaction(i, nil, &sa) sigaction(i, nil, &sa)
@ -260,6 +266,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
sigprocmask(_SIG_SETMASK, sigset(m[0])) sigprocmask(_SIG_SETMASK, sigset(m[0]))
} }

View File

@ -107,7 +107,7 @@ func getRandomData(r []byte) {
func goenvs() { func goenvs() {
} }
func initsig() { func initsig(preinit bool) {
} }
//go:nosplit //go:nosplit

View File

@ -279,6 +279,8 @@ func memlimit() uintptr {
func sigtramp() func sigtramp()
//go:nosplit
//go:nowritebarrierrec
func setsig(i int32, fn uintptr, restart bool) { func setsig(i int32, fn uintptr, restart bool) {
var sa sigactiont var sa sigactiont
@ -295,6 +297,8 @@ func setsig(i int32, fn uintptr, restart bool) {
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func setsigstack(i int32) { func setsigstack(i int32) {
var sa sigactiont var sa sigactiont
sigaction(i, nil, &sa) sigaction(i, nil, &sa)
@ -306,6 +310,8 @@ func setsigstack(i int32) {
sigaction(i, &sa, nil) sigaction(i, &sa, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func getsig(i int32) uintptr { func getsig(i int32) uintptr {
var sa sigactiont var sa sigactiont
sigaction(i, nil, &sa) sigaction(i, nil, &sa)
@ -328,6 +334,8 @@ func signalstack(s *stack) {
sigaltstack(&st, nil) sigaltstack(&st, nil)
} }
//go:nosplit
//go:nowritebarrierrec
func updatesigmask(m sigmask) { func updatesigmask(m sigmask) {
var mask sigset var mask sigset
copy(mask.__sigbits[:], m[:]) 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))) 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 */ { func raise(sig int32) /* int32 */ {
sysvicall1(&libc_raise, uintptr(sig)) 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))) 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 */ { func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ {
sysvicall3(&libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact))) 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:nosplit
//go:nowritebarrierrec
func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ { func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset))) sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
} }

View File

@ -1088,7 +1088,7 @@ func mstart1() {
cgoHasExtraM = true cgoHasExtraM = true
newextram() newextram()
} }
initsig() initsig(false)
} }
if fn := _g_.m.mstartfn; fn != nil { if fn := _g_.m.mstartfn; fn != nil {

View File

@ -25,6 +25,10 @@ TEXT _rt0_386_darwin_lib(SB),NOSPLIT,$0
MOVL 12(BP), AX MOVL 12(BP), AX
MOVL AX, _rt0_386_darwin_lib_argv<>(SB) MOVL AX, _rt0_386_darwin_lib_argv<>(SB)
// Synchronous initialization.
MOVL $runtime·libpreinit(SB), AX
CALL AX
SUBL $12, SP SUBL $12, SP
// Create a new thread to do the runtime initialization and return. // Create a new thread to do the runtime initialization and return.

View File

@ -23,6 +23,10 @@ TEXT _rt0_amd64_darwin_lib(SB),NOSPLIT,$0x48
MOVQ DI, _rt0_amd64_darwin_lib_argc<>(SB) MOVQ DI, _rt0_amd64_darwin_lib_argc<>(SB)
MOVQ SI, _rt0_amd64_darwin_lib_argv<>(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. // Create a new thread to do the runtime initialization and return.
MOVQ _cgo_sys_thread_create(SB), AX MOVQ _cgo_sys_thread_create(SB), AX
TESTQ AX, AX TESTQ AX, AX

View File

@ -25,6 +25,10 @@ TEXT _rt0_arm_darwin_lib(SB),NOSPLIT,$0
MOVW R0, _rt0_arm_darwin_lib_argc<>(SB) MOVW R0, _rt0_arm_darwin_lib_argc<>(SB)
MOVW R1, _rt0_arm_darwin_lib_argv<>(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. // Create a new thread to do the runtime initialization and return.
MOVW _cgo_sys_thread_create(SB), R3 MOVW _cgo_sys_thread_create(SB), R3
CMP $0, R3 CMP $0, R3

View File

@ -25,6 +25,11 @@ TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$0
MOVD R0, _rt0_arm64_darwin_lib_argc<>(SB) MOVD R0, _rt0_arm64_darwin_lib_argc<>(SB)
MOVD R1, _rt0_arm64_darwin_lib_argv<>(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. // Create a new thread to do the runtime initialization and return.
MOVD _cgo_sys_thread_create(SB), R4 MOVD _cgo_sys_thread_create(SB), R4
MOVD $_rt0_arm64_darwin_lib_go(SB), R0 MOVD $_rt0_arm64_darwin_lib_go(SB), R0

View File

@ -26,6 +26,10 @@ TEXT _rt0_386_linux_lib(SB),NOSPLIT,$0
MOVL 12(BP), AX MOVL 12(BP), AX
MOVL AX, _rt0_386_linux_lib_argv<>(SB) MOVL AX, _rt0_386_linux_lib_argv<>(SB)
// Synchronous initialization.
MOVL $runtime·libpreinit(SB), AX
CALL AX
SUBL $8, SP SUBL $8, SP
// Create a new thread to do the runtime initialization. // Create a new thread to do the runtime initialization.

View File

@ -23,6 +23,10 @@ TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x48
MOVQ DI, _rt0_amd64_linux_lib_argc<>(SB) MOVQ DI, _rt0_amd64_linux_lib_argc<>(SB)
MOVQ SI, _rt0_amd64_linux_lib_argv<>(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. // Create a new thread to do the runtime initialization and return.
MOVQ _cgo_sys_thread_create(SB), AX MOVQ _cgo_sys_thread_create(SB), AX
TESTQ AX, AX TESTQ AX, AX

View File

@ -26,6 +26,10 @@ TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$32
MOVW R0, _rt0_arm_linux_lib_argc<>(SB) MOVW R0, _rt0_arm_linux_lib_argc<>(SB)
MOVW R1, _rt0_arm_linux_lib_argv<>(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. // Create a new thread to do the runtime initialization.
MOVW _cgo_sys_thread_create(SB), R2 MOVW _cgo_sys_thread_create(SB), R2
CMP $0, R2 CMP $0, R2

View File

@ -20,6 +20,10 @@ TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$40
MOVD R0, _rt0_arm64_linux_lib_argc<>(SB) MOVD R0, _rt0_arm64_linux_lib_argc<>(SB)
MOVD R1, _rt0_arm64_linux_lib_argv<>(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. // Create a new thread to do the runtime initialization and return.
MOVD _cgo_sys_thread_create(SB), R4 MOVD _cgo_sys_thread_create(SB), R4
CMP $0, R4 CMP $0, R4

View File

@ -34,15 +34,33 @@ var (
maskUpdatedChan chan struct{} maskUpdatedChan chan struct{}
) )
func initsig() { func init() {
// _NSIG is the number of signals on this operating system. // _NSIG is the number of signals on this operating system.
// sigtable should describe what to do for all the possible signals. // sigtable should describe what to do for all the possible signals.
if len(sigtable) != _NSIG { if len(sigtable) != _NSIG {
print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n") 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++ { for i := int32(0); i < _NSIG; i++ {
t := &sigtable[i] t := &sigtable[i]
if t.flags == 0 || t.flags&_SigDefault != 0 { if t.flags == 0 || t.flags&_SigDefault != 0 {
@ -64,6 +82,8 @@ func initsig() {
} }
} }
//go:nosplit
//go:nowritebarrierrec
func sigInstallGoHandler(sig int32) bool { func sigInstallGoHandler(sig int32) bool {
// For some signals, we respect an inherited SIG_IGN handler // For some signals, we respect an inherited SIG_IGN handler
// rather than insist on installing our own default handler. // rather than insist on installing our own default handler.
@ -101,6 +121,7 @@ func sigenable(sig uint32) {
<-maskUpdatedChan <-maskUpdatedChan
if t.flags&_SigHandling == 0 { if t.flags&_SigHandling == 0 {
t.flags |= _SigHandling t.flags |= _SigHandling
fwdSig[sig] = getsig(int32(sig))
setsig(int32(sig), funcPC(sighandler), true) setsig(int32(sig), funcPC(sighandler), true)
} }
} }
@ -163,6 +184,8 @@ func sigpipe() {
// dieFromSignal kills the program with a signal. // dieFromSignal kills the program with a signal.
// This provides the expected exit status for the shell. // This provides the expected exit status for the shell.
// This is only called with fatal signals expected to kill the process. // This is only called with fatal signals expected to kill the process.
//go:nosplit
//go:nowritebarrierrec
func dieFromSignal(sig int32) { func dieFromSignal(sig int32) {
setsig(sig, _SIG_DFL, false) setsig(sig, _SIG_DFL, false)
updatesigmask(sigmask{}) updatesigmask(sigmask{})

View File

@ -22,6 +22,20 @@ func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
return false return false
} }
fwdFn := fwdSig[sig] 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 flags := sigtable[sig].flags
// If there is no handler to forward to, no need to forward. // If there is no handler to forward to, no need to forward.

View File

@ -191,7 +191,7 @@ func setBadSignalMsg() {
// Following are not implemented. // Following are not implemented.
func initsig() { func initsig(preinit bool) {
} }
func sigenable(sig uint32) { func sigenable(sig uint32) {