...

Source file src/runtime/signal_sighandler.go

     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		printDebugLog()
   152	
   153		exit(2)
   154	}
   155	

View as plain text