]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: move sighandler into signal_unix.go
authorIan Lance Taylor <iant@golang.org>
Fri, 11 Oct 2019 16:52:11 +0000 (09:52 -0700)
committerIan Lance Taylor <iant@golang.org>
Fri, 11 Oct 2019 17:28:42 +0000 (17:28 +0000)
We couldn't do this before because sighandler was compiled for nacl.

Updates #30439

Change-Id: Ieec9938b6a1796c48d251cd8b1db1a42c25f3943
Reviewed-on: https://go-review.googlesource.com/c/go/+/200739
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/runtime/signal_sighandler.go [deleted file]
src/runtime/signal_unix.go

diff --git a/src/runtime/signal_sighandler.go b/src/runtime/signal_sighandler.go
deleted file mode 100644 (file)
index b81957e..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
-
-package runtime
-
-import (
-       "unsafe"
-)
-
-// crashing is the number of m's we have waited for when implementing
-// GOTRACEBACK=crash when a signal is received.
-var crashing int32
-
-// testSigtrap is used by the runtime tests. If non-nil, it is called
-// on SIGTRAP. If it returns true, the normal behavior on SIGTRAP is
-// suppressed.
-var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool
-
-// sighandler is invoked when a signal occurs. The global g will be
-// set to a gsignal goroutine and we will be running on the alternate
-// signal stack. The parameter g will be the value of the global g
-// when the signal occurred. The sig, info, and ctxt parameters are
-// from the system signal handler: they are the parameters passed when
-// the SA is passed to the sigaction system call.
-//
-// The garbage collector may have stopped the world, 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(c.sigpc(), c.sigsp(), c.siglr(), gp, _g_.m)
-               return
-       }
-
-       if sig == _SIGTRAP && testSigtrap != nil && testSigtrap(info, (*sigctxt)(noescape(unsafe.Pointer(c))), gp) {
-               return
-       }
-
-       flags := int32(_SigThrow)
-       if sig < uint32(len(sigtable)) {
-               flags = sigtable[sig].flags
-       }
-       if flags&_SigPanic != 0 && gp.throwsplit {
-               // We can't safely sigpanic because it may grow the
-               // stack. Abort in the signal handler instead.
-               flags = (flags &^ _SigPanic) | _SigThrow
-       }
-       if isAbortPC(c.sigpc()) {
-               // On many architectures, the abort function just
-               // causes a memory fault. Don't turn that into a panic.
-               flags = _SigThrow
-       }
-       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
-               // The signal is going to cause a panic.
-               // Arrange the stack so that it looks like the point
-               // where the signal occurred made a call to the
-               // function sigpanic. Then set the PC to sigpanic.
-
-               // 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.fault())
-               gp.sigpc = c.sigpc()
-
-               c.preparePanic(sig, gp)
-               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(sig)
-       }
-
-       if flags&_SigThrow == 0 {
-               return
-       }
-
-       _g_.m.throwing = 1
-       _g_.m.caughtsig.set(gp)
-
-       if crashing == 0 {
-               startpanic_m()
-       }
-
-       if sig < uint32(len(sigtable)) {
-               print(sigtable[sig].name, "\n")
-       } else {
-               print("Signal ", sig, "\n")
-       }
-
-       print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n")
-       if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
-               print("signal arrived during cgo execution\n")
-               gp = _g_.m.lockedg.ptr()
-       }
-       print("\n")
-
-       level, _, docrash := gotraceback()
-       if level > 0 {
-               goroutineheader(gp)
-               tracebacktrap(c.sigpc(), c.sigsp(), c.siglr(), 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, _g_.m.curg)
-               } else if crashing == 0 {
-                       tracebackothers(gp)
-                       print("\n")
-               }
-               dumpregs(c)
-       }
-
-       if docrash {
-               crashing++
-               if crashing < mcount()-int32(extraMCount) {
-                       // 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()
-       }
-
-       printDebugLog()
-
-       exit(2)
-}
index 6a8b5b7ace50722802514be54e25c25644fa250c..a9a65d51640b1da6f2239cb07d903158d9669f53 100644 (file)
@@ -370,6 +370,149 @@ func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
        }
 }
 
+// crashing is the number of m's we have waited for when implementing
+// GOTRACEBACK=crash when a signal is received.
+var crashing int32
+
+// testSigtrap is used by the runtime tests. If non-nil, it is called
+// on SIGTRAP. If it returns true, the normal behavior on SIGTRAP is
+// suppressed.
+var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool
+
+// sighandler is invoked when a signal occurs. The global g will be
+// set to a gsignal goroutine and we will be running on the alternate
+// signal stack. The parameter g will be the value of the global g
+// when the signal occurred. The sig, info, and ctxt parameters are
+// from the system signal handler: they are the parameters passed when
+// the SA is passed to the sigaction system call.
+//
+// The garbage collector may have stopped the world, 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(c.sigpc(), c.sigsp(), c.siglr(), gp, _g_.m)
+               return
+       }
+
+       if sig == _SIGTRAP && testSigtrap != nil && testSigtrap(info, (*sigctxt)(noescape(unsafe.Pointer(c))), gp) {
+               return
+       }
+
+       flags := int32(_SigThrow)
+       if sig < uint32(len(sigtable)) {
+               flags = sigtable[sig].flags
+       }
+       if flags&_SigPanic != 0 && gp.throwsplit {
+               // We can't safely sigpanic because it may grow the
+               // stack. Abort in the signal handler instead.
+               flags = (flags &^ _SigPanic) | _SigThrow
+       }
+       if isAbortPC(c.sigpc()) {
+               // On many architectures, the abort function just
+               // causes a memory fault. Don't turn that into a panic.
+               flags = _SigThrow
+       }
+       if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+               // The signal is going to cause a panic.
+               // Arrange the stack so that it looks like the point
+               // where the signal occurred made a call to the
+               // function sigpanic. Then set the PC to sigpanic.
+
+               // 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.fault())
+               gp.sigpc = c.sigpc()
+
+               c.preparePanic(sig, gp)
+               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(sig)
+       }
+
+       if flags&_SigThrow == 0 {
+               return
+       }
+
+       _g_.m.throwing = 1
+       _g_.m.caughtsig.set(gp)
+
+       if crashing == 0 {
+               startpanic_m()
+       }
+
+       if sig < uint32(len(sigtable)) {
+               print(sigtable[sig].name, "\n")
+       } else {
+               print("Signal ", sig, "\n")
+       }
+
+       print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n")
+       if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+               print("signal arrived during cgo execution\n")
+               gp = _g_.m.lockedg.ptr()
+       }
+       print("\n")
+
+       level, _, docrash := gotraceback()
+       if level > 0 {
+               goroutineheader(gp)
+               tracebacktrap(c.sigpc(), c.sigsp(), c.siglr(), 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, _g_.m.curg)
+               } else if crashing == 0 {
+                       tracebackothers(gp)
+                       print("\n")
+               }
+               dumpregs(c)
+       }
+
+       if docrash {
+               crashing++
+               if crashing < mcount()-int32(extraMCount) {
+                       // 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()
+       }
+
+       printDebugLog()
+
+       exit(2)
+}
+
 // sigpanic turns a synchronous signal into a run-time panic.
 // If the signal handler sees a synchronous panic, it arranges the
 // stack to look like the function where the signal occurred called