libgo: update to go1.9
[official-gcc.git] / libgo / go / runtime / signal_sighandler.go
blob378c68e1d9086a563496fa6857968ba02142e196
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 c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
44 // Emulate gc by passing arguments out of band,
45 // although we don't really have to.
46 gp.sig = sig
47 gp.sigcode0 = uintptr(c.sigcode())
48 gp.sigcode1 = sigfault
49 gp.sigpc = sigpc
51 setg(gp)
53 // All signals were blocked due to the sigaction mask;
54 // unblock them.
55 var set sigset
56 sigfillset(&set)
57 sigprocmask(_SIG_UNBLOCK, &set, nil)
59 sigpanic()
60 throw("sigpanic returned")
63 if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
64 if sigsend(sig) {
65 return
69 if c.sigcode() == _SI_USER && signal_ignored(sig) {
70 return
73 if flags&_SigKill != 0 {
74 dieFromSignal(sig)
77 if flags&_SigThrow == 0 {
78 return
81 _g_.m.throwing = 1
82 _g_.m.caughtsig.set(gp)
84 if crashing == 0 {
85 startpanic()
88 if sig < uint32(len(sigtable)) {
89 print(sigtable[sig].name, "\n")
90 } else {
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")
97 gp = _g_.m.lockedg
99 print("\n")
101 level, _, docrash := gotraceback()
102 if level > 0 {
103 goroutineheader(gp)
104 traceback(0)
105 if crashing == 0 {
106 tracebackothers(gp)
107 print("\n")
109 dumpregs(info, ctxt)
112 if docrash {
113 crashing++
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.
125 print("\n-----\n\n")
126 raiseproc(_SIGQUIT)
127 usleep(5 * 1000 * 1000)
129 crash()
132 exit(2)