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.
5 // +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
13 // crashing is the number of m's we have waited for when implementing
14 // GOTRACEBACK=crash when a signal is received.
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.
24 // The garbage collector may have stopped the world, so write barriers
27 //go:nowritebarrierrec
28 func sighandler(sig
uint32, info
*_siginfo_t
, ctxt unsafe
.Pointer
, gp
*g
) {
30 c
:= sigctxt
{info
, ctxt
}
32 sigfault
, sigpc
:= getSiginfo(info
, ctxt
)
35 sigprof(sigpc
, gp
, _g_
.m
)
39 flags
:= int32(_SigThrow
)
40 if sig
< uint32(len(sigtable
)) {
41 flags
= sigtable
[sig
].flags
43 if c
.sigcode() != _SI_USER
&& flags
&_SigPanic
!= 0 {
44 // Emulate gc by passing arguments out of band,
45 // although we don't really have to.
47 gp
.sigcode0
= uintptr(c
.sigcode())
48 gp
.sigcode1
= sigfault
53 // All signals were blocked due to the sigaction mask;
57 sigprocmask(_SIG_UNBLOCK
, &set
, nil)
60 throw("sigpanic returned")
63 if c
.sigcode() == _SI_USER || flags
&_SigNotify
!= 0 {
69 if c
.sigcode() == _SI_USER
&& signal_ignored(sig
) {
73 if flags
&_SigKill
!= 0 {
77 if flags
&_SigThrow
== 0 {
82 _g_
.m
.caughtsig
.set(gp
)
88 if sig
< uint32(len(sigtable
)) {
89 print(sigtable
[sig
].name
, "\n")
91 print("Signal ", sig
, "\n")
94 print("PC=", hex(sigpc
), " m=", _g_
.m
.id
, " sigcode=", c
.sigcode(), "\n")
95 if _g_
.m
.lockedg
!= nil && _g_
.m
.ncgo
> 0 && gp
== _g_
.m
.g0
{
96 print("signal arrived during cgo execution\n")
101 level
, _
, docrash
:= gotraceback()
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.
127 usleep(5 * 1000 * 1000)