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.
4
5// This file implements runtime support for signal handling.
6//
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.
11//
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
25// nor deadlocks.
26
27// +build !plan9
28
29package runtime
30
31import (
32	"runtime/internal/atomic"
33	_ "unsafe" // for go:linkname
34)
35
36// sig handles communication between the signal handler and os/signal.
37// Other than the inuse and recv fields, the fields are accessed atomically.
38//
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.
47var sig struct {
48	note       note
49	mask       [(_NSIG + 31) / 32]uint32
50	wanted     [(_NSIG + 31) / 32]uint32
51	ignored    [(_NSIG + 31) / 32]uint32
52	recv       [(_NSIG + 31) / 32]uint32
53	state      uint32
54	delivering uint32
55	inuse      bool
56}
57
58const (
59	sigIdle = iota
60	sigReceiving
61	sigSending
62)
63
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.
67func sigsend(s uint32) bool {
68	bit := uint32(1) << uint(s&31)
69	if !sig.inuse || s >= uint32(32*len(sig.wanted)) {
70		return false
71	}
72
73	atomic.Xadd(&sig.delivering, 1)
74	// We are running in the signal handler; defer is not available.
75
76	if w := atomic.Load(&sig.wanted[s/32]); w&bit == 0 {
77		atomic.Xadd(&sig.delivering, -1)
78		return false
79	}
80
81	// Add signal to outgoing queue.
82	for {
83		mask := sig.mask[s/32]
84		if mask&bit != 0 {
85			atomic.Xadd(&sig.delivering, -1)
86			return true // signal already in queue
87		}
88		if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
89			break
90		}
91	}
92
93	// Notify receiver that queue has new bit.
94Send:
95	for {
96		switch atomic.Load(&sig.state) {
97		default:
98			throw("sigsend: inconsistent state")
99		case sigIdle:
100			if atomic.Cas(&sig.state, sigIdle, sigSending) {
101				break Send
102			}
103		case sigSending:
104			// notification already pending
105			break Send
106		case sigReceiving:
107			if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
108				notewakeup(&sig.note)
109				break Send
110			}
111		}
112	}
113
114	atomic.Xadd(&sig.delivering, -1)
115	return true
116}
117
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
121func signal_recv() uint32 {
122	for {
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)
127				return i
128			}
129		}
130
131		// Wait for updates to be available from signal sender.
132	Receive:
133		for {
134			switch atomic.Load(&sig.state) {
135			default:
136				throw("signal_recv: inconsistent state")
137			case sigIdle:
138				if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
139					notetsleepg(&sig.note, -1)
140					noteclear(&sig.note)
141					break Receive
142				}
143			case sigSending:
144				if atomic.Cas(&sig.state, sigSending, sigIdle) {
145					break Receive
146				}
147			}
148		}
149
150		// Incorporate updates from sender into local copy.
151		for i := range sig.mask {
152			sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
153		}
154	}
155}
156
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
165func 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 {
172		Gosched()
173	}
174
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 {
179		Gosched()
180	}
181}
182
183// Must only be called from a single goroutine at a time.
184//go:linkname signal_enable os_signal.signal_enable
185func signal_enable(s uint32) {
186	if !sig.inuse {
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
191		noteclear(&sig.note)
192		return
193	}
194
195	if s >= uint32(len(sig.wanted)*32) {
196		return
197	}
198
199	w := sig.wanted[s/32]
200	w |= 1 << (s & 31)
201	atomic.Store(&sig.wanted[s/32], w)
202
203	i := sig.ignored[s/32]
204	i &^= 1 << (s & 31)
205	atomic.Store(&sig.ignored[s/32], i)
206
207	sigenable(s)
208}
209
210// Must only be called from a single goroutine at a time.
211//go:linkname signal_disable os_signal.signal_disable
212func signal_disable(s uint32) {
213	if s >= uint32(len(sig.wanted)*32) {
214		return
215	}
216	sigdisable(s)
217
218	w := sig.wanted[s/32]
219	w &^= 1 << (s & 31)
220	atomic.Store(&sig.wanted[s/32], w)
221}
222
223// Must only be called from a single goroutine at a time.
224//go:linkname signal_ignore os_signal.signal_ignore
225func signal_ignore(s uint32) {
226	if s >= uint32(len(sig.wanted)*32) {
227		return
228	}
229	sigignore(s)
230
231	w := sig.wanted[s/32]
232	w &^= 1 << (s & 31)
233	atomic.Store(&sig.wanted[s/32], w)
234
235	i := sig.ignored[s/32]
236	i |= 1 << (s & 31)
237	atomic.Store(&sig.ignored[s/32], i)
238}
239
240// Checked by signal handlers.
241func signal_ignored(s uint32) bool {
242	i := atomic.Load(&sig.ignored[s/32])
243	return i&(1<<(s&31)) != 0
244}
245