github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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 c.sigcode() != _SI_USER && flags&_SigPanic != 0 { 42 // The signal is going to cause a panic. 43 // Arrange the stack so that it looks like the point 44 // where the signal occurred made a call to the 45 // function sigpanic. Then set the PC to sigpanic. 46 47 // Have to pass arguments out of band since 48 // augmenting the stack frame would break 49 // the unwinding code. 50 gp.sig = sig 51 gp.sigcode0 = uintptr(c.sigcode()) 52 gp.sigcode1 = uintptr(c.fault()) 53 gp.sigpc = c.sigpc() 54 55 c.preparePanic(sig, gp) 56 return 57 } 58 59 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 { 60 if sigsend(sig) { 61 return 62 } 63 } 64 65 if c.sigcode() == _SI_USER && signal_ignored(sig) { 66 return 67 } 68 69 if flags&_SigKill != 0 { 70 dieFromSignal(sig) 71 } 72 73 if flags&_SigThrow == 0 { 74 return 75 } 76 77 _g_.m.throwing = 1 78 _g_.m.caughtsig.set(gp) 79 80 if crashing == 0 { 81 startpanic() 82 } 83 84 if sig < uint32(len(sigtable)) { 85 print(sigtable[sig].name, "\n") 86 } else { 87 print("Signal ", sig, "\n") 88 } 89 90 print("PC=", hex(c.sigpc()), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n") 91 if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 { 92 print("signal arrived during cgo execution\n") 93 gp = _g_.m.lockedg 94 } 95 print("\n") 96 97 level, _, docrash := gotraceback() 98 if level > 0 { 99 goroutineheader(gp) 100 tracebacktrap(c.sigpc(), c.sigsp(), c.siglr(), gp) 101 if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning { 102 // tracebackothers on original m skipped this one; trace it now. 103 goroutineheader(_g_.m.curg) 104 traceback(^uintptr(0), ^uintptr(0), 0, gp) 105 } else if crashing == 0 { 106 tracebackothers(gp) 107 print("\n") 108 } 109 dumpregs(c) 110 } 111 112 if docrash { 113 crashing++ 114 if crashing < sched.mcount { 115 // There are other m's that need to dump their stacks. 116 // Relay SIGQUIT to the next m by sending it to the current process. 117 // All m's that have already received SIGQUIT have signal masks blocking 118 // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet. 119 // When the last m receives the SIGQUIT, it will fall through to the call to 120 // crash below. Just in case the relaying gets botched, each m involved in 121 // the relay sleeps for 5 seconds and then does the crash/exit itself. 122 // In expected operation, the last m has received the SIGQUIT and run 123 // crash/exit and the process is gone, all long before any of the 124 // 5-second sleeps have finished. 125 print("\n-----\n\n") 126 raiseproc(_SIGQUIT) 127 usleep(5 * 1000 * 1000) 128 } 129 crash() 130 } 131 132 exit(2) 133 }