diff options
author | Ian Lance Taylor <iant@golang.org> | 2016-09-23 22:05:51 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2016-09-25 03:55:33 +0000 |
commit | 159a90b93a962cb942688f099b42d00d164e436f (patch) | |
tree | 5742f50b4f74e1284512a50cf55dacb6cbf1f7ee /src/runtime/signal_mips64x.go | |
parent | 890c09efb72f11b3e6fd95d859260bfee7de7f31 (diff) | |
download | go-159a90b93a962cb942688f099b42d00d164e436f.tar.gz go-159a90b93a962cb942688f099b42d00d164e436f.zip |
runtime: merge Unix sighandler functions
Replace all the Unix sighandler functions with a single instance.
Push the relatively small amount of processor-specific code into five
methods on sigctxt: sigpc, sigsp, siglr, fault, preparePanic.
(Some processors already had a fault method.)
Change-Id: Ib459412ff8f7e0f5ad06bfd43eb827c8b196fc32
Reviewed-on: https://go-review.googlesource.com/29752
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Diffstat (limited to 'src/runtime/signal_mips64x.go')
-rw-r--r-- | src/runtime/signal_mips64x.go | 163 |
1 files changed, 33 insertions, 130 deletions
diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go index 4dbeb42fe5..900009e957 100644 --- a/src/runtime/signal_mips64x.go +++ b/src/runtime/signal_mips64x.go @@ -51,138 +51,41 @@ func dumpregs(c *sigctxt) { print("hi ", hex(c.hi()), "\n") } -var crashing int32 - -// May run during STW, so write barriers are not allowed. -// -//go:nowritebarrierrec -func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { - _g_ := getg() - c := &sigctxt{info, ctxt} - - if sig == _SIGPROF { - sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp, _g_.m) - return - } - flags := int32(_SigThrow) - if sig < uint32(len(sigtable)) { - flags = sigtable[sig].flags - } - if c.sigcode() != _SI_USER && flags&_SigPanic != 0 { - // Make it look like a call to the signal func. - // Have to pass arguments out of band since - // augmenting the stack frame would break - // the unwinding code. - gp.sig = sig - gp.sigcode0 = uintptr(c.sigcode()) - gp.sigcode1 = uintptr(c.sigaddr()) - gp.sigpc = uintptr(c.pc()) - - // We arrange link, and pc to pretend the panicking - // function calls sigpanic directly. - // Always save LINK to stack so that panics in leaf - // functions are correctly handled. This smashes - // the stack frame but we're not going back there - // anyway. - sp := c.sp() - sys.PtrSize - c.set_sp(sp) - *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link() - - pc := gp.sigpc - - // If we don't recognize the PC as code - // but we do recognize the link register as code, - // then assume this was a call to non-code and treat like - // pc == 0, to make unwinding show the context. - if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil { - pc = 0 - } - - // Don't bother saving PC if it's zero, which is - // probably a call to a nil func: the old link register - // is more useful in the stack trace. - if pc != 0 { - c.set_link(uint64(pc)) - } - - // In case we are panicking from external C code - c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) - c.set_pc(uint64(funcPC(sigpanic))) - return - } - - if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { - if sigsend(sig) { - return - } - } - - if c.sigcode() == _SI_USER && signal_ignored(sig) { - return - } - - if flags&_SigKill != 0 { - dieFromSignal(int32(sig)) - } - - if flags&_SigThrow == 0 { - return - } - - _g_.m.throwing = 1 - _g_.m.caughtsig.set(gp) - - if crashing == 0 { - startpanic() - } - - if sig < uint32(len(sigtable)) { - print(sigtable[sig].name, "\n") - } else { - print("Signal ", sig, "\n") - } - - print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n") - if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { - print("signal arrived during cgo execution\n") - gp = _g_.m.lockedg - } - print("\n") - - level, _, docrash := gotraceback() - if level > 0 { - goroutineheader(gp) - tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp) - if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { - // tracebackothers on original m skipped this one; trace it now. - goroutineheader(_g_.m.curg) - traceback(^uintptr(0), ^uintptr(0), 0, gp) - } else if crashing == 0 { - tracebackothers(gp) - print("\n") - } - dumpregs(c) +func (c *sigctxt) sigpc() uintptr { return uintptr(c.pc()) } +func (c *sigctxt) sigsp() uintptr { return uintptr(c.sp()) } +func (c *sigctxt) siglr() uintptr { return uintptr(c.link()) } +func (c *sigctxt) fault() uintptr { return uintptr(c.sigaddr()) } + +// preparePanic sets up the stack to look like a call to sigpanic. +func (c *sigctxt) preparePanic(sig uint32, gp *g) { + // We arrange link, and pc to pretend the panicking + // function calls sigpanic directly. + // Always save LINK to stack so that panics in leaf + // functions are correctly handled. This smashes + // the stack frame but we're not going back there + // anyway. + sp := c.sp() - sys.PtrSize + c.set_sp(sp) + *(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link() + + pc := gp.sigpc + + // If we don't recognize the PC as code + // but we do recognize the link register as code, + // then assume this was a call to non-code and treat like + // pc == 0, to make unwinding show the context. + if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil { + pc = 0 } - if docrash { - crashing++ - if crashing < sched.mcount { - // There are other m's that need to dump their stacks. - // Relay SIGQUIT to the next m by sending it to the current process. - // All m's that have already received SIGQUIT have signal masks blocking - // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. - // When the last m receives the SIGQUIT, it will fall through to the call to - // crash below. Just in case the relaying gets botched, each m involved in - // the relay sleeps for 5 seconds and then does the crash/exit itself. - // In expected operation, the last m has received the SIGQUIT and run - // crash/exit and the process is gone, all long before any of the - // 5-second sleeps have finished. - print("\n-----\n\n") - raiseproc(_SIGQUIT) - usleep(5 * 1000 * 1000) - } - crash() + // Don't bother saving PC if it's zero, which is + // probably a call to a nil func: the old link register + // is more useful in the stack trace. + if pc != 0 { + c.set_link(uint64(pc)) } - exit(2) + // In case we are panicking from external C code + c.set_r30(uint64(uintptr(unsafe.Pointer(gp)))) + c.set_pc(uint64(funcPC(sigpanic))) } |