mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: signal forwarding for darwin/amd64
Follows the linux signal forwarding semantics from http://golang.org/cl/8712, sharing the implementation of sigfwdgo. Forwarding for 386, arm, and arm64 will follow. Change-Id: I6bf30d563d19da39b6aec6900c7fe12d82ed4f62 Reviewed-on: https://go-review.googlesource.com/9302 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
c20ff36fe2
commit
a5b693b431
10 changed files with 106 additions and 76 deletions
|
|
@ -12,6 +12,9 @@ func lwp_create(param *lwpparams) int32
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigaltstack(new, old *sigaltstackt)
|
func sigaltstack(new, old *sigaltstackt)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigaction(sig int32, new, old *sigactiont)
|
func sigaction(sig int32, new, old *sigactiont)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ func thr_new(param *thrparam, size int32)
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigaltstack(new, old *stackt)
|
func sigaltstack(new, old *stackt)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigaction(sig int32, new, old *sigactiont)
|
func sigaction(sig int32, new, old *sigactiont)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,10 @@ func sigpanic() {
|
||||||
panicmem()
|
panicmem()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
||||||
|
throw("sigfwd not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
func raiseproc(sig int32) {
|
func raiseproc(sig int32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,11 @@ func sigaction(sig int32, new, old *sigactiont)
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigaltstack(new, old *sigaltstackt)
|
func sigaltstack(new, old *sigaltstackt)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
||||||
|
throw("sigfwd not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigprocmask(mode int32, new, old *sigset)
|
func sigprocmask(mode int32, new, old *sigset)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func setitimer(mode int32, new, old *itimerval)
|
func setitimer(mode int32, new, old *itimerval)
|
||||||
|
|
||||||
|
|
@ -13,6 +15,9 @@ func sigaction(sig int32, new, old *sigactiont)
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigaltstack(new, old *stackt)
|
func sigaltstack(new, old *stackt)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
|
||||||
|
|
||||||
//go:noescape
|
//go:noescape
|
||||||
func sigprocmask(mode int32, new uint32) uint32
|
func sigprocmask(mode int32, new uint32) uint32
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ type libcFunc uintptr
|
||||||
|
|
||||||
var asmsysvicall6 libcFunc
|
var asmsysvicall6 libcFunc
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
|
||||||
|
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func sysvicall0(fn libcFunc) uintptr {
|
func sysvicall0(fn libcFunc) uintptr {
|
||||||
libcall := &getg().m.libcall
|
libcall := &getg().m.libcall
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
type sigTabT struct {
|
type sigTabT struct {
|
||||||
flags int32
|
flags int32
|
||||||
name string
|
name string
|
||||||
|
|
@ -43,3 +45,27 @@ var sigtable = [...]sigTabT{
|
||||||
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
|
/* 30 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
|
||||||
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
|
/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
|
||||||
|
|
||||||
|
//go:noescape
|
||||||
|
func sigreturn(ctx unsafe.Pointer, infostyle uint32)
|
||||||
|
|
||||||
|
//go:nosplit
|
||||||
|
func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
||||||
|
if sigfwdgo(sig, info, ctx) {
|
||||||
|
sigreturn(ctx, infostyle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g := getg()
|
||||||
|
if g == nil {
|
||||||
|
badsignal(uintptr(sig))
|
||||||
|
sigreturn(ctx, infostyle)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setg(g.m.gsignal)
|
||||||
|
sighandler(sig, info, ctx, g)
|
||||||
|
setg(g)
|
||||||
|
sigreturn(ctx, infostyle)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,40 +79,6 @@ var sigtable = [...]sigTabT{
|
||||||
/* 64 */ {_SigNotify, "signal 64"},
|
/* 64 */ {_SigNotify, "signal 64"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determines if the signal should be handled by Go and if not, forwards the
|
|
||||||
// signal to the handler that was installed before Go's. Returns whether the
|
|
||||||
// signal was forwarded.
|
|
||||||
//go:nosplit
|
|
||||||
func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
|
|
||||||
g := getg()
|
|
||||||
c := &sigctxt{info, ctx}
|
|
||||||
if sig >= uint32(len(sigtable)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
fwdFn := fwdSig[sig]
|
|
||||||
flags := sigtable[sig].flags
|
|
||||||
|
|
||||||
// If there is no handler to forward to, no need to forward.
|
|
||||||
if fwdFn == _SIG_DFL {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Only forward synchronous signals.
|
|
||||||
if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Determine if the signal occurred inside Go code. We test that:
|
|
||||||
// (1) we were in a goroutine (i.e., m.curg != nil), and
|
|
||||||
// (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
|
|
||||||
if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Signal not handled by Go, forward it.
|
|
||||||
if fwdFn != _SIG_IGN {
|
|
||||||
sigfwd(fwdFn, sig, info, ctx)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Continuation of the (assembly) sigtramp() logic.
|
// Continuation of the (assembly) sigtramp() logic.
|
||||||
//go:nosplit
|
//go:nosplit
|
||||||
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,43 @@
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import _ "unsafe" // for go:linkname
|
import "unsafe"
|
||||||
|
|
||||||
//go:linkname os_sigpipe os.sigpipe
|
//go:linkname os_sigpipe os.sigpipe
|
||||||
func os_sigpipe() {
|
func os_sigpipe() {
|
||||||
systemstack(sigpipe)
|
systemstack(sigpipe)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if the signal should be handled by Go and if not, forwards the
|
||||||
|
// signal to the handler that was installed before Go's. Returns whether the
|
||||||
|
// signal was forwarded.
|
||||||
|
//go:nosplit
|
||||||
|
func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
|
||||||
|
g := getg()
|
||||||
|
c := &sigctxt{info, ctx}
|
||||||
|
if sig >= uint32(len(sigtable)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
fwdFn := fwdSig[sig]
|
||||||
|
flags := sigtable[sig].flags
|
||||||
|
|
||||||
|
// If there is no handler to forward to, no need to forward.
|
||||||
|
if fwdFn == _SIG_DFL {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Only forward synchronous signals.
|
||||||
|
if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Determine if the signal occurred inside Go code. We test that:
|
||||||
|
// (1) we were in a goroutine (i.e., m.curg != nil), and
|
||||||
|
// (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
|
||||||
|
if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Signal not handled by Go, forward it.
|
||||||
|
if fwdFn != _SIG_IGN {
|
||||||
|
sigfwd(fwdFn, sig, info, ctx)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
|
||||||
MOVL $0xf1, 0xf1 // crash
|
MOVL $0xf1, 0xf1 // crash
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·sigaction(SB),NOSPLIT,$0
|
TEXT runtime·sigaction(SB),NOSPLIT,$0-24
|
||||||
MOVL mode+0(FP), DI // arg 1 sig
|
MOVL mode+0(FP), DI // arg 1 sig
|
||||||
MOVQ new+8(FP), SI // arg 2 act
|
MOVQ new+8(FP), SI // arg 2 act
|
||||||
MOVQ old+16(FP), DX // arg 3 oact
|
MOVQ old+16(FP), DX // arg 3 oact
|
||||||
|
|
@ -212,49 +212,30 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
|
||||||
MOVL $0xf1, 0xf1 // crash
|
MOVL $0xf1, 0xf1 // crash
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT runtime·sigtramp(SB),NOSPLIT,$64
|
TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
|
||||||
get_tls(BX)
|
MOVQ fn+0(FP), AX
|
||||||
|
MOVQ sig+8(FP), DI
|
||||||
MOVQ R8, 32(SP) // save ucontext
|
MOVQ info+16(FP), SI
|
||||||
MOVQ SI, 40(SP) // save infostyle
|
MOVQ ctx+24(FP), DX
|
||||||
|
|
||||||
// check that g exists
|
|
||||||
MOVQ g(BX), R10
|
|
||||||
CMPQ R10, $0
|
|
||||||
JNE 5(PC)
|
|
||||||
MOVL DX, 0(SP)
|
|
||||||
MOVQ $runtime·badsignal(SB), AX
|
|
||||||
CALL AX
|
CALL AX
|
||||||
JMP ret
|
RET
|
||||||
|
|
||||||
// save g
|
TEXT runtime·sigreturn(SB),NOSPLIT,$0-12
|
||||||
MOVQ R10, 48(SP)
|
MOVQ ctx+0(FP), DI
|
||||||
|
MOVL infostyle+8(FP), SI
|
||||||
// g = m->gsignal
|
MOVL $(0x2000000+184), AX
|
||||||
MOVQ g_m(R10), BP
|
|
||||||
MOVQ m_gsignal(BP), BP
|
|
||||||
MOVQ BP, g(BX)
|
|
||||||
|
|
||||||
MOVL DX, 0(SP)
|
|
||||||
MOVQ CX, 8(SP)
|
|
||||||
MOVQ R8, 16(SP)
|
|
||||||
MOVQ R10, 24(SP)
|
|
||||||
|
|
||||||
CALL DI
|
|
||||||
|
|
||||||
// restore g
|
|
||||||
get_tls(BX)
|
|
||||||
MOVQ 48(SP), R10
|
|
||||||
MOVQ R10, g(BX)
|
|
||||||
|
|
||||||
ret:
|
|
||||||
// call sigreturn
|
|
||||||
MOVL $(0x2000000+184), AX // sigreturn(ucontext, infostyle)
|
|
||||||
MOVQ 32(SP), DI // saved ucontext
|
|
||||||
MOVQ 40(SP), SI // saved infostyle
|
|
||||||
SYSCALL
|
SYSCALL
|
||||||
INT $3 // not reached
|
INT $3 // not reached
|
||||||
|
|
||||||
|
TEXT runtime·sigtramp(SB),NOSPLIT,$32
|
||||||
|
MOVQ DI, 0(SP) // fn
|
||||||
|
MOVL SI, 8(SP) // infostyle
|
||||||
|
MOVL DX, 12(SP) // sig
|
||||||
|
MOVQ CX, 16(SP) // info
|
||||||
|
MOVQ R8, 24(SP) // ctx
|
||||||
|
MOVQ $runtime·sigtrampgo(SB), AX
|
||||||
|
CALL AX
|
||||||
|
|
||||||
TEXT runtime·mmap(SB),NOSPLIT,$0
|
TEXT runtime·mmap(SB),NOSPLIT,$0
|
||||||
MOVQ addr+0(FP), DI // arg 1 addr
|
MOVQ addr+0(FP), DI // arg 1 addr
|
||||||
MOVQ n+8(FP), SI // arg 2 len
|
MOVQ n+8(FP), SI // arg 2 len
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue