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:
parent
0b3807a2a3
commit
21b4f234c7
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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[:])
|
||||||
|
@ -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[:])
|
||||||
|
@ -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)
|
||||||
|
@ -67,7 +67,7 @@ func goenvs() {
|
|||||||
goenvs_unix()
|
goenvs_unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
func initsig() {
|
func initsig(preinit bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
|
@ -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[:])
|
||||||
|
@ -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]))
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ func getRandomData(r []byte) {
|
|||||||
func goenvs() {
|
func goenvs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func initsig() {
|
func initsig(preinit bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
|
@ -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)))
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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{})
|
||||||
|
@ -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.
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user