github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/runtime/signal_sighandler.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris 6 7 package runtime 8 9 import ( 10 "unsafe" 11 ) 12 13 // crashing is the number of m's we have waited for when implementing 14 // GOTRACEBACK=crash when a signal is received. 15 var crashing int32 16 17 // testSigtrap is used by the runtime tests. If non-nil, it is called 18 // on SIGTRAP. If it returns true, the normal behavior on SIGTRAP is 19 // suppressed. 20 var testSigtrap func(info *siginfo, ctxt *sigctxt, gp *g) bool 21 22 // sighandler is invoked when a signal occurs. The global g will be 23 // set to a gsignal goroutine and we will be running on the alternate 24 // signal stack. The parameter g will be the value of the global g 25 // when the signal occurred. The sig, info, and ctxt parameters are 26 // from the system signal handler: they are the parameters passed when 27 // the SA is passed to the sigaction system call. 28 // 29 // The garbage collector may have stopped the world, so write barriers 30 // are not allowed. 31 // 32 //go:nowritebarrierrec 33 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { 34 _g_ := getg() 35 c := &sigctxt{info, ctxt} 36 37 if sig == _SIGPROF { 38 sigprof(c.sigpc(), c.sigsp(), c.siglr(), gp, _g_.m) 39 return 40 } 41 42 if sig == _SIGTRAP && testSigtrap != nil && testSigtrap(info, (*sigctxt)(noescape(unsafe.Pointer(c))), gp) { 43 return 44 } 45 46 flags := int32(_SigThrow) 47 if sig < uint32(len(sigtable)) { 48 flags = sigtable[sig].flags 49 } 50 if flags&_SigPanic != 0 && gp.throwsplit { 51 // We can't safely sigpanic because it may grow the 52 // stack. Abort in the signal handler instead. 53 flags = (flags &^ _SigPanic) | _SigThrow 54 } 55 if isAbortPC(c.sigpc()) { 56 // On many architectures, the abort function just 57 // causes a memory fault. Don't turn that into a panic. 58 flags = _SigThrow 59 } 60 if c.sigcode() != _SI_USER && flags&_SigPanic != 0 { 61 // The signal is going to cause a panic. 62 // Arrange the stack so that it looks like the point 63 // where the signal occurred made a call to the 64 // function sigpanic. Then set the PC to sigpanic. 65 66 // Have to pass arguments out of band since 67 // augmenting the stack frame would break 68 // the unwinding code. 69 gp.sig = sig 70 gp.sigcode0 = uintptr(c.sigcode()) 71 gp.sigcode1 = uintptr(c.fault()) 72 gp.sigpc = c.sigpc() 73 74 c.preparePanic(sig, gp) 75 return 76 } 77 78 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { 79 if sigsend(sig) { 80 return 81 } 82 } 83 84 if c.sigcode() == _SI_USER && signal_ignored(sig) { 85 return 86 } 87 88 if flags&_SigKill != 0 { 89 dieFromSignal(sig) 90 } 91 92 if flags&_SigThrow == 0 { 93 return 94 } 95 96 _g_.m.throwing = 1 97 _g_.m.caughtsig.set(gp) 98 99 if crashing == 0 { 100 startpanic_m() 101 } 102 103 if sig < uint32(len(sigtable)) { 104 print(sigtable[sig].name, "\n") 105 } else { 106 print("Signal ", sig, "\n") 107 } 108 109 print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n") 110 if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 { 111 print("signal arrived during cgo execution\n") 112 gp = _g_.m.lockedg.ptr() 113 } 114 print("\n") 115 116 level, _, docrash := gotraceback() 117 if level > 0 { 118 goroutineheader(gp) 119 tracebacktrap(c.sigpc(), c.sigsp(), c.siglr(), gp) 120 if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { 121 // tracebackothers on original m skipped this one; trace it now. 122 goroutineheader(_g_.m.curg) 123 traceback(^uintptr(0), ^uintptr(0), 0, _g_.m.curg) 124 } else if crashing == 0 { 125 tracebackothers(gp) 126 print("\n") 127 } 128 dumpregs(c) 129 } 130 131 if docrash { 132 crashing++ 133 if crashing < mcount()-int32(extraMCount) { 134 // There are other m's that need to dump their stacks. 135 // Relay SIGQUIT to the next m by sending it to the current process. 136 // All m's that have already received SIGQUIT have signal masks blocking 137 // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. 138 // When the last m receives the SIGQUIT, it will fall through to the call to 139 // crash below. Just in case the relaying gets botched, each m involved in 140 // the relay sleeps for 5 seconds and then does the crash/exit itself. 141 // In expected operation, the last m has received the SIGQUIT and run 142 // crash/exit and the process is gone, all long before any of the 143 // 5-second sleeps have finished. 144 print("\n-----\n\n") 145 raiseproc(_SIGQUIT) 146 usleep(5 * 1000 * 1000) 147 } 148 crash() 149 } 150 151 exit(2) 152 }