runtime: scan register backing store on ia64
[official-gcc.git] / libgo / go / runtime / signal_sighandler.go
blob698629d154fdd60715cd32e6bd5defae9257622e
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
7 package runtime
9 import (
10 "unsafe"
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
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
25 // are not allowed.
27 //go:nowritebarrierrec
28 func sighandler(sig uint32, info *_siginfo_t, ctxt unsafe.Pointer, gp *g) {
29 _g_ := getg()
30 c := sigctxt{info, ctxt}
32 sigfault, sigpc := getSiginfo(info, ctxt)
34 if sig == _SIGPROF {
35 sigprof(sigpc, gp, _g_.m)
36 return
39 flags := int32(_SigThrow)
40 if sig < uint32(len(sigtable)) {
41 flags = sigtable[sig].flags
43 if flags&_SigPanic != 0 && gp.throwsplit {
44 // We can't safely sigpanic because it may grow the
45 // stack. Abort in the signal handler instead.
46 flags = (flags &^ _SigPanic) | _SigThrow
48 if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
49 // Emulate gc by passing arguments out of band,
50 // although we don't really have to.
51 gp.sig = sig
52 gp.sigcode0 = uintptr(c.sigcode())
53 gp.sigcode1 = sigfault
54 gp.sigpc = sigpc
56 setg(gp)
58 // All signals were blocked due to the sigaction mask;
59 // unblock them.
60 var set sigset
61 sigfillset(&set)
62 sigprocmask(_SIG_UNBLOCK, &set, nil)
64 sigpanic()
65 throw("sigpanic returned")
68 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
69 if sigsend(sig) {
70 return
74 if c.sigcode() == _SI_USER && signal_ignored(sig) {
75 return
78 if flags&_SigKill != 0 {
79 dieFromSignal(sig)
82 if flags&_SigThrow == 0 {
83 return
86 _g_.m.throwing = 1
87 _g_.m.caughtsig.set(gp)
89 if crashing == 0 {
90 startpanic()
93 if sig < uint32(len(sigtable)) {
94 print(sigtable[sig].name, "\n")
95 } else {
96 print("Signal ", sig, "\n")
99 print("PC=", hex(sigpc), " m=", _g_.m.id, " sigcode=", c.sigcode(), "\n")
100 if _g_.m.lockedg != 0 && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
101 print("signal arrived during cgo execution\n")
102 gp = _g_.m.lockedg.ptr()
104 print("\n")
106 level, _, docrash := gotraceback()
107 if level > 0 {
108 goroutineheader(gp)
109 traceback(0)
110 if crashing == 0 {
111 tracebackothers(gp)
112 print("\n")
114 dumpregs(info, ctxt)
117 if docrash {
118 crashing++
119 if crashing < mcount()-int32(extraMCount) {
120 // There are other m's that need to dump their stacks.
121 // Relay SIGQUIT to the next m by sending it to the current process.
122 // All m's that have already received SIGQUIT have signal masks blocking
123 // receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
124 // When the last m receives the SIGQUIT, it will fall through to the call to
125 // crash below. Just in case the relaying gets botched, each m involved in
126 // the relay sleeps for 5 seconds and then does the crash/exit itself.
127 // In expected operation, the last m has received the SIGQUIT and run
128 // crash/exit and the process is gone, all long before any of the
129 // 5-second sleeps have finished.
130 print("\n-----\n\n")
131 raiseproc(_SIGQUIT)
132 usleep(5 * 1000 * 1000)
134 crash()
137 exit(2)