aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/os1_nacl.go16
-rw-r--r--src/runtime/signal1_unix.go35
-rw-r--r--src/runtime/signal_darwin.go2
-rw-r--r--src/runtime/signal_freebsd.go2
-rw-r--r--src/runtime/signal_openbsd.go2
-rw-r--r--src/runtime/signal_sigtramp.go2
-rw-r--r--src/runtime/signal_solaris_amd64.go4
-rw-r--r--src/runtime/sigqueue.go18
-rw-r--r--src/runtime/sys_solaris_amd64.s5
9 files changed, 63 insertions, 23 deletions
diff --git a/src/runtime/os1_nacl.go b/src/runtime/os1_nacl.go
index 6fc2819cdd..622755119d 100644
--- a/src/runtime/os1_nacl.go
+++ b/src/runtime/os1_nacl.go
@@ -174,6 +174,22 @@ func memlimit() uintptr {
// This runs on a foreign stack, without an m or a g. No stack split.
//go:nosplit
+//go:norace
+//go:nowritebarrierrec
+func badsignal(sig uintptr) {
+ cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+}
+
+func badsignalgo(sig uintptr) {
+ if !sigsend(uint32(sig)) {
+ // A foreign thread received the signal sig, and the
+ // Go code does not want to handle it.
+ raisebadsignal(int32(sig))
+ }
+}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+//go:nosplit
func badsignal2() {
write(2, unsafe.Pointer(&badsignal1[0]), int32(len(badsignal1)))
exit(2)
diff --git a/src/runtime/signal1_unix.go b/src/runtime/signal1_unix.go
index 8e4d425fde..31c1f2c4e5 100644
--- a/src/runtime/signal1_unix.go
+++ b/src/runtime/signal1_unix.go
@@ -6,7 +6,10 @@
package runtime
-import "runtime/internal/sys"
+import (
+ "runtime/internal/sys"
+ "unsafe"
+)
const (
_SIG_DFL uintptr = 0
@@ -197,7 +200,7 @@ func dieFromSignal(sig int32) {
// raisebadsignal is called when a signal is received on a non-Go
// thread, and the Go program does not want to handle it (that is, the
// program has not called os/signal.Notify for the signal).
-func raisebadsignal(sig int32) {
+func raisebadsignal(sig int32, c *sigctxt) {
if sig == _SIGPROF {
// Ignore profiling signals that arrive on non-Go threads.
return
@@ -220,6 +223,18 @@ func raisebadsignal(sig int32) {
// again.
unblocksig(sig)
setsig(sig, handler, false)
+
+ // If we're linked into a non-Go program we want to try to
+ // avoid modifying the original context in which the signal
+ // was raised. If the handler is the default, we know it
+ // is non-recoverable, so we don't have to worry about
+ // re-installing sighandler. At this point we can just
+ // return and the signal will be re-raised and caught by
+ // the default handler with the correct context.
+ if (isarchive || islibrary) && handler == _SIG_DFL && c.sigcode() != _SI_USER {
+ return
+ }
+
raise(sig)
// If the signal didn't cause the program to exit, restore the
@@ -307,3 +322,19 @@ func sigNotOnStack(sig uint32) {
println("signal", sig, "received but handler not on signal stack")
throw("non-Go code set up signal handler without SA_ONSTACK flag")
}
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+//go:nosplit
+//go:norace
+//go:nowritebarrierrec
+func badsignal(sig uintptr, c *sigctxt) {
+ cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig)+unsafe.Sizeof(c))
+}
+
+func badsignalgo(sig uintptr, c *sigctxt) {
+ if !sigsend(uint32(sig)) {
+ // A foreign thread received the signal sig, and the
+ // Go code does not want to handle it.
+ raisebadsignal(int32(sig), c)
+ }
+}
diff --git a/src/runtime/signal_darwin.go b/src/runtime/signal_darwin.go
index 8d43724e2f..c8534ff09b 100644
--- a/src/runtime/signal_darwin.go
+++ b/src/runtime/signal_darwin.go
@@ -58,7 +58,7 @@ func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Poi
}
g := getg()
if g == nil {
- badsignal(uintptr(sig))
+ badsignal(uintptr(sig), &sigctxt{info, ctx})
sigreturn(ctx, infostyle)
return
}
diff --git a/src/runtime/signal_freebsd.go b/src/runtime/signal_freebsd.go
index f3411aac6a..cd2068a62c 100644
--- a/src/runtime/signal_freebsd.go
+++ b/src/runtime/signal_freebsd.go
@@ -55,7 +55,7 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
}
g := getg()
if g == nil {
- badsignal(uintptr(sig))
+ badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
diff --git a/src/runtime/signal_openbsd.go b/src/runtime/signal_openbsd.go
index d0239b1d91..3c50190da4 100644
--- a/src/runtime/signal_openbsd.go
+++ b/src/runtime/signal_openbsd.go
@@ -55,7 +55,7 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
}
g := getg()
if g == nil {
- badsignal(uintptr(sig))
+ badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
diff --git a/src/runtime/signal_sigtramp.go b/src/runtime/signal_sigtramp.go
index 00ab03846e..18fc375e24 100644
--- a/src/runtime/signal_sigtramp.go
+++ b/src/runtime/signal_sigtramp.go
@@ -18,7 +18,7 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
}
g := getg()
if g == nil {
- badsignal(uintptr(sig))
+ badsignal(uintptr(sig), &sigctxt{info, ctx})
return
}
diff --git a/src/runtime/signal_solaris_amd64.go b/src/runtime/signal_solaris_amd64.go
index a577c8c199..7ba368f25b 100644
--- a/src/runtime/signal_solaris_amd64.go
+++ b/src/runtime/signal_solaris_amd64.go
@@ -11,6 +11,10 @@ type sigctxt struct {
ctxt unsafe.Pointer
}
+func makesigctxt(info *siginfo, ctxt unsafe.Pointer) *sigctxt {
+ return &sigctxt{info, ctxt}
+}
+
func (c *sigctxt) regs() *mcontext {
return (*mcontext)(unsafe.Pointer(&(*ucontext)(c.ctxt).uc_mcontext))
}
diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go
index e86e6a5636..0162ffa04f 100644
--- a/src/runtime/sigqueue.go
+++ b/src/runtime/sigqueue.go
@@ -30,7 +30,7 @@ package runtime
import (
"runtime/internal/atomic"
- "unsafe"
+ _ "unsafe" // for go:linkname
)
var sig struct {
@@ -176,19 +176,3 @@ func signal_ignore(s uint32) {
func signal_ignored(s uint32) bool {
return sig.ignored[s/32]&(1<<(s&31)) != 0
}
-
-// This runs on a foreign stack, without an m or a g. No stack split.
-//go:nosplit
-//go:norace
-//go:nowritebarrierrec
-func badsignal(sig uintptr) {
- cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
-}
-
-func badsignalgo(sig uintptr) {
- if !sigsend(uint32(sig)) {
- // A foreign thread received the signal sig, and the
- // Go code does not want to handle it.
- raisebadsignal(int32(sig))
- }
-}
diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s
index 09f22636a9..f8b7da5c62 100644
--- a/src/runtime/sys_solaris_amd64.s
+++ b/src/runtime/sys_solaris_amd64.s
@@ -173,7 +173,12 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$0
MOVQ g(BX), R10
CMPQ R10, $0
JNE allgood
+ MOVQ SI, 0(SP)
+ MOVQ DX, 8(SP)
+ CALL runtime·makesigctxt(SB)
+ MOVQ 16(SP), AX
MOVQ DI, 0(SP)
+ MOVQ AX, 8(SP)
MOVQ $runtime·badsignal(SB), AX
CALL AX
JMP exit