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 29 package runtime 30 31 import ( 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. 47 var 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 58 const ( 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. 67 func 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. 94 Send: 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 if GOOS == "darwin" { 109 sigNoteWakeup(&sig.note) 110 break Send 111 } 112 notewakeup(&sig.note) 113 break Send 114 } 115 } 116 } 117 118 atomic.Xadd(&sig.delivering, -1) 119 return true 120 } 121 122 // Called to receive the next queued signal. 123 // Must only be called from a single goroutine at a time. 124 //go:linkname signal_recv os/signal.signal_recv 125 func signal_recv() uint32 { 126 for { 127 // Serve any signals from local copy. 128 for i := uint32(0); i < _NSIG; i++ { 129 if sig.recv[i/32]&(1<<(i&31)) != 0 { 130 sig.recv[i/32] &^= 1 << (i & 31) 131 return i 132 } 133 } 134 135 // Wait for updates to be available from signal sender. 136 Receive: 137 for { 138 switch atomic.Load(&sig.state) { 139 default: 140 throw("signal_recv: inconsistent state") 141 case sigIdle: 142 if atomic.Cas(&sig.state, sigIdle, sigReceiving) { 143 if GOOS == "darwin" { 144 sigNoteSleep(&sig.note) 145 break Receive 146 } 147 notetsleepg(&sig.note, -1) 148 noteclear(&sig.note) 149 break Receive 150 } 151 case sigSending: 152 if atomic.Cas(&sig.state, sigSending, sigIdle) { 153 break Receive 154 } 155 } 156 } 157 158 // Incorporate updates from sender into local copy. 159 for i := range sig.mask { 160 sig.recv[i] = atomic.Xchg(&sig.mask[i], 0) 161 } 162 } 163 } 164 165 // signalWaitUntilIdle waits until the signal delivery mechanism is idle. 166 // This is used to ensure that we do not drop a signal notification due 167 // to a race between disabling a signal and receiving a signal. 168 // This assumes that signal delivery has already been disabled for 169 // the signal(s) in question, and here we are just waiting to make sure 170 // that all the signals have been delivered to the user channels 171 // by the os/signal package. 172 //go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle 173 func signalWaitUntilIdle() { 174 // Although the signals we care about have been removed from 175 // sig.wanted, it is possible that another thread has received 176 // a signal, has read from sig.wanted, is now updating sig.mask, 177 // and has not yet woken up the processor thread. We need to wait 178 // until all current signal deliveries have completed. 179 for atomic.Load(&sig.delivering) != 0 { 180 Gosched() 181 } 182 183 // Although WaitUntilIdle seems like the right name for this 184 // function, the state we are looking for is sigReceiving, not 185 // sigIdle. The sigIdle state is really more like sigProcessing. 186 for atomic.Load(&sig.state) != sigReceiving { 187 Gosched() 188 } 189 } 190 191 // Must only be called from a single goroutine at a time. 192 //go:linkname signal_enable os/signal.signal_enable 193 func signal_enable(s uint32) { 194 if !sig.inuse { 195 // The first call to signal_enable is for us 196 // to use for initialization. It does not pass 197 // signal information in m. 198 sig.inuse = true // enable reception of signals; cannot disable 199 if GOOS == "darwin" { 200 sigNoteSetup(&sig.note) 201 return 202 } 203 noteclear(&sig.note) 204 return 205 } 206 207 if s >= uint32(len(sig.wanted)*32) { 208 return 209 } 210 211 w := sig.wanted[s/32] 212 w |= 1 << (s & 31) 213 atomic.Store(&sig.wanted[s/32], w) 214 215 i := sig.ignored[s/32] 216 i &^= 1 << (s & 31) 217 atomic.Store(&sig.ignored[s/32], i) 218 219 sigenable(s) 220 } 221 222 // Must only be called from a single goroutine at a time. 223 //go:linkname signal_disable os/signal.signal_disable 224 func signal_disable(s uint32) { 225 if s >= uint32(len(sig.wanted)*32) { 226 return 227 } 228 sigdisable(s) 229 230 w := sig.wanted[s/32] 231 w &^= 1 << (s & 31) 232 atomic.Store(&sig.wanted[s/32], w) 233 } 234 235 // Must only be called from a single goroutine at a time. 236 //go:linkname signal_ignore os/signal.signal_ignore 237 func signal_ignore(s uint32) { 238 if s >= uint32(len(sig.wanted)*32) { 239 return 240 } 241 sigignore(s) 242 243 w := sig.wanted[s/32] 244 w &^= 1 << (s & 31) 245 atomic.Store(&sig.wanted[s/32], w) 246 247 i := sig.ignored[s/32] 248 i |= 1 << (s & 31) 249 atomic.Store(&sig.ignored[s/32], i) 250 } 251 252 // sigInitIgnored marks the signal as already ignored. This is called at 253 // program start by initsig. In a shared library initsig is called by 254 // libpreinit, so the runtime may not be initialized yet. 255 //go:nosplit 256 func sigInitIgnored(s uint32) { 257 i := sig.ignored[s/32] 258 i |= 1 << (s & 31) 259 atomic.Store(&sig.ignored[s/32], i) 260 } 261 262 // Checked by signal handlers. 263 //go:linkname signal_ignored os/signal.signal_ignored 264 func signal_ignored(s uint32) bool { 265 i := atomic.Load(&sig.ignored[s/32]) 266 return i&(1<<(s&31)) != 0 267 } 268