golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/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, _g_.m.curg)
   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-int32(extraMCount) {
   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  }