1 // Copyright 2009 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 // This file implements runtime support for signal handling.
7 // Most synchronization primitives are not available from
8 // the signal handler (it cannot block, allocate memory, or use locks)
9 // so the handler communicates with a processing goroutine
10 // via struct sig, below.
12 // sigsend is called by the signal handler to queue a new signal.
13 // signal_recv is called by the Go program to receive a newly queued signal.
14 // Synchronization between sigsend and signal_recv is based on the sig.state
15 // variable. It can be in 3 states: sigIdle, sigReceiving and sigSending.
16 // sigReceiving means that signal_recv is blocked on sig.Note and there are no
17 // new pending signals.
18 // sigSending means that sig.mask *may* contain new pending signals,
19 // signal_recv can't be blocked in this state.
20 // sigIdle means that there are no new pending signals and signal_recv is not blocked.
21 // Transitions between states are done atomically with CAS.
22 // When signal_recv is unblocked, it resets sig.Note and rechecks sig.mask.
23 // If several sigsends and signal_recv execute concurrently, it can lead to
24 // unnecessary rechecks of sig.mask, but it cannot lead to missed signals
32 "runtime/internal/atomic"
33 _
"unsafe" // for go:linkname
36 // sig handles communication between the signal handler and os/signal.
37 // Other than the inuse and recv fields, the fields are accessed atomically.
39 // The wanted and ignored fields are only written by one goroutine at
40 // a time; access is controlled by the handlers Mutex in os/signal.
41 // The fields are only read by that one goroutine and by the signal handler.
42 // We access them atomically to minimize the race between setting them
43 // in the goroutine calling os/signal and the signal handler,
44 // which may be running in a different thread. That race is unavoidable,
45 // as there is no connection between handling a signal and receiving one,
46 // but atomic instructions should minimize it.
49 mask
[(_NSIG
+ 31) / 32]uint32
50 wanted
[(_NSIG
+ 31) / 32]uint32
51 ignored
[(_NSIG
+ 31) / 32]uint32
52 recv
[(_NSIG
+ 31) / 32]uint32
64 // sigsend delivers a signal from sighandler to the internal signal delivery queue.
65 // It reports whether the signal was sent. If not, the caller typically crashes the program.
66 // It runs from the signal handler, so it's limited in what it can do.
67 func sigsend(s
uint32) bool {
68 bit
:= uint32(1) << uint(s
&31)
69 if !sig
.inuse || s
>= uint32(32*len(sig
.wanted
)) {
73 atomic
.Xadd(&sig
.delivering
, 1)
74 // We are running in the signal handler; defer is not available.
76 if w
:= atomic
.Load(&sig
.wanted
[s
/32]); w
&bit
== 0 {
77 atomic
.Xadd(&sig
.delivering
, -1)
81 // Add signal to outgoing queue.
83 mask
:= sig
.mask
[s
/32]
85 atomic
.Xadd(&sig
.delivering
, -1)
86 return true // signal already in queue
88 if atomic
.Cas(&sig
.mask
[s
/32], mask
, mask|bit
) {
93 // Notify receiver that queue has new bit.
96 switch atomic
.Load(&sig
.state
) {
98 throw("sigsend: inconsistent state")
100 if atomic
.Cas(&sig
.state
, sigIdle
, sigSending
) {
104 // notification already pending
107 if atomic
.Cas(&sig
.state
, sigReceiving
, sigIdle
) {
108 notewakeup(&sig
.note
)
114 atomic
.Xadd(&sig
.delivering
, -1)
118 // Called to receive the next queued signal.
119 // Must only be called from a single goroutine at a time.
120 //go:linkname signal_recv os_signal.signal_recv
121 func signal_recv() uint32 {
123 // Serve any signals from local copy.
124 for i
:= uint32(0); i
< _NSIG
; i
++ {
125 if sig
.recv
[i
/32]&(1<<(i
&31)) != 0 {
126 sig
.recv
[i
/32] &^= 1 << (i
& 31)
131 // Wait for updates to be available from signal sender.
134 switch atomic
.Load(&sig
.state
) {
136 throw("signal_recv: inconsistent state")
138 if atomic
.Cas(&sig
.state
, sigIdle
, sigReceiving
) {
139 notetsleepg(&sig
.note
, -1)
144 if atomic
.Cas(&sig
.state
, sigSending
, sigIdle
) {
150 // Incorporate updates from sender into local copy.
151 for i
:= range sig
.mask
{
152 sig
.recv
[i
] = atomic
.Xchg(&sig
.mask
[i
], 0)
157 // signalWaitUntilIdle waits until the signal delivery mechanism is idle.
158 // This is used to ensure that we do not drop a signal notification due
159 // to a race between disabling a signal and receiving a signal.
160 // This assumes that signal delivery has already been disabled for
161 // the signal(s) in question, and here we are just waiting to make sure
162 // that all the signals have been delivered to the user channels
163 // by the os/signal package.
164 //go:linkname signalWaitUntilIdle os_signal.signalWaitUntilIdle
165 func signalWaitUntilIdle() {
166 // Although the signals we care about have been removed from
167 // sig.wanted, it is possible that another thread has received
168 // a signal, has read from sig.wanted, is now updating sig.mask,
169 // and has not yet woken up the processor thread. We need to wait
170 // until all current signal deliveries have completed.
171 for atomic
.Load(&sig
.delivering
) != 0 {
175 // Although WaitUntilIdle seems like the right name for this
176 // function, the state we are looking for is sigReceiving, not
177 // sigIdle. The sigIdle state is really more like sigProcessing.
178 for atomic
.Load(&sig
.state
) != sigReceiving
{
183 // Must only be called from a single goroutine at a time.
184 //go:linkname signal_enable os_signal.signal_enable
185 func signal_enable(s
uint32) {
187 // The first call to signal_enable is for us
188 // to use for initialization. It does not pass
189 // signal information in m.
190 sig
.inuse
= true // enable reception of signals; cannot disable
195 if s
>= uint32(len(sig
.wanted
)*32) {
199 w
:= sig
.wanted
[s
/32]
201 atomic
.Store(&sig
.wanted
[s
/32], w
)
203 i
:= sig
.ignored
[s
/32]
205 atomic
.Store(&sig
.ignored
[s
/32], i
)
210 // Must only be called from a single goroutine at a time.
211 //go:linkname signal_disable os_signal.signal_disable
212 func signal_disable(s
uint32) {
213 if s
>= uint32(len(sig
.wanted
)*32) {
218 w
:= sig
.wanted
[s
/32]
220 atomic
.Store(&sig
.wanted
[s
/32], w
)
223 // Must only be called from a single goroutine at a time.
224 //go:linkname signal_ignore os_signal.signal_ignore
225 func signal_ignore(s
uint32) {
226 if s
>= uint32(len(sig
.wanted
)*32) {
231 w
:= sig
.wanted
[s
/32]
233 atomic
.Store(&sig
.wanted
[s
/32], w
)
235 i
:= sig
.ignored
[s
/32]
237 atomic
.Store(&sig
.ignored
[s
/32], i
)
240 // Checked by signal handlers.
241 func signal_ignored(s
uint32) bool {
242 i
:= atomic
.Load(&sig
.ignored
[s
/32])
243 return i
&(1<<(s
&31)) != 0