...
Run Format

Source file src/runtime/signal_sighandler.go

Documentation: runtime

     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  // 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  }
   153  

View as plain text