...
Run Format

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 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 {
   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	}
   134	

View as plain text