github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/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 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 // sighandler is invoked when a signal occurs. The global g will be 18 // set to a gsignal goroutine and we will be running on the alternate 19 // signal stack. The parameter g will be the value of the global g 20 // when the signal occurred. The sig, info, and ctxt parameters are 21 // from the system signal handler: they are the parameters passed when 22 // the SA is passed to the sigaction system call. 23 // 24 // The garbage collector may have stopped the world, so write barriers 25 // are not allowed. 26 // 27 //go:nowritebarrierrec 28 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) { 29 _g_ := getg() 30 c := &sigctxt{info, ctxt} 31 32 if sig == _SIGPROF { 33 sigprof(c.sigpc(), c.sigsp(), c.siglr(), gp, _g_.m) 34 return 35 } 36 37 flags := int32(_SigThrow) 38 if sig < uint32(len(sigtable)) { 39 flags = sigtable[sig].flags 40 } 41 if flags&_SigPanic != 0 && gp.throwsplit { 42 // We can't safely sigpanic because it may grow the 43 // stack. Abort in the signal handler instead. 44 flags = (flags &^ _SigPanic) | _SigThrow 45 } 46 if c.sigcode() != _SI_USER && flags&_SigPanic != 0 { 47 // The signal is going to cause a panic. 48 // Arrange the stack so that it looks like the point 49 // where the signal occurred made a call to the 50 // function sigpanic. Then set the PC to sigpanic. 51 52 // Have to pass arguments out of band since 53 // augmenting the stack frame would break 54 // the unwinding code. 55 gp.sig = sig 56 gp.sigcode0 = uintptr(c.sigcode()) 57 gp.sigcode1 = uintptr(c.fault()) 58 gp.sigpc = c.sigpc() 59 60 c.preparePanic(sig, gp) 61 return 62 } 63 64 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { 65 if sigsend(sig) { 66 return 67 } 68 } 69 70 if c.sigcode() == _SI_USER && signal_ignored(sig) { 71 return 72 } 73 74 if flags&_SigKill != 0 { 75 dieFromSignal(sig) 76 } 77 78 if flags&_SigThrow == 0 { 79 return 80 } 81 82 _g_.m.throwing = 1 83 _g_.m.caughtsig.set(gp) 84 85 if crashing == 0 { 86 startpanic() 87 } 88 89 if sig < uint32(len(sigtable)) { 90 print(sigtable[sig].name, "\n") 91 } else { 92 print("Signal ", sig, "\n") 93 } 94 95 print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n") 96 if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 { 97 print("signal arrived during cgo execution\n") 98 gp = _g_.m.lockedg.ptr() 99 } 100 print("\n") 101 102 level, _, docrash := gotraceback() 103 if level > 0 { 104 goroutineheader(gp) 105 tracebacktrap(c.sigpc(), c.sigsp(), c.siglr(), gp) 106 if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { 107 // tracebackothers on original m skipped this one; trace it now. 108 goroutineheader(_g_.m.curg) 109 traceback(^uintptr(0), ^uintptr(0), 0, _g_.m.curg) 110 } else if crashing == 0 { 111 tracebackothers(gp) 112 print("\n") 113 } 114 dumpregs(c) 115 } 116 117 if docrash { 118 crashing++ 119 if crashing < mcount()-int32(extraMCount) { 120 // There are other m's that need to dump their stacks. 121 // Relay SIGQUIT to the next m by sending it to the current process. 122 // All m's that have already received SIGQUIT have signal masks blocking 123 // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. 124 // When the last m receives the SIGQUIT, it will fall through to the call to 125 // crash below. Just in case the relaying gets botched, each m involved in 126 // the relay sleeps for 5 seconds and then does the crash/exit itself. 127 // In expected operation, the last m has received the SIGQUIT and run 128 // crash/exit and the process is gone, all long before any of the 129 // 5-second sleeps have finished. 130 print("\n-----\n\n") 131 raiseproc(_SIGQUIT) 132 usleep(5 * 1000 * 1000) 133 } 134 crash() 135 } 136 137 exit(2) 138 }