github.com/remobjects/goldbaselibrary@v0.0.0-20230924164425-d458680a936b/Source/Gold/os/signal/signal.go (about) 1 // Copyright 2012 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 package signal 6 7 import ( 8 "os" 9 "sync" 10 ) 11 12 var handlers struct { 13 sync.Mutex 14 // Map a channel to the signals that should be sent to it. 15 m map[chan<- os.Signal]*handler 16 // Map a signal to the number of channels receiving it. 17 ref [numSig]int64 18 // Map channels to signals while the channel is being stopped. 19 // Not a map because entries live here only very briefly. 20 // We need a separate container because we need m to correspond to ref 21 // at all times, and we also need to keep track of the *handler 22 // value for a channel being stopped. See the Stop function. 23 stopping []stopping 24 } 25 26 type stopping struct { 27 c chan<- os.Signal 28 h *handler 29 } 30 31 type handler struct { 32 mask [(numSig + 31) / 32]uint32 33 } 34 35 func (h *handler) want(sig int) bool { 36 return (h.mask[sig/32]>>uint(sig&31))&1 != 0 37 } 38 39 func (h *handler) set(sig int) { 40 h.mask[sig/32] |= 1 << uint(sig&31) 41 } 42 43 func (h *handler) clear(sig int) { 44 h.mask[sig/32] &^= 1 << uint(sig&31) 45 } 46 47 // Stop relaying the signals, sigs, to any channels previously registered to 48 // receive them and either reset the signal handlers to their original values 49 // (action=disableSignal) or ignore the signals (action=ignoreSignal). 50 func cancel(sigs []os.Signal, action func(int)) { 51 handlers.Lock() 52 defer handlers.Unlock() 53 54 remove := func(n int) { 55 var zerohandler handler 56 57 for c, h := range handlers.m { 58 if h.want(n) { 59 handlers.ref[n]-- 60 h.clear(n) 61 if h.mask == zerohandler.mask { 62 delete(handlers.m, c) 63 } 64 } 65 } 66 67 action(n) 68 } 69 70 if len(sigs) == 0 { 71 for n := 0; n < numSig; n++ { 72 remove(n) 73 } 74 } else { 75 for _, s := range sigs { 76 remove(signum(s)) 77 } 78 } 79 } 80 81 // Ignore causes the provided signals to be ignored. If they are received by 82 // the program, nothing will happen. Ignore undoes the effect of any prior 83 // calls to Notify for the provided signals. 84 // If no signals are provided, all incoming signals will be ignored. 85 func Ignore(sig ...os.Signal) { 86 cancel(sig, ignoreSignal) 87 } 88 89 // Ignored reports whether sig is currently ignored. 90 func Ignored(sig os.Signal) bool { 91 sn := signum(sig) 92 return sn >= 0 && signalIgnored(sn) 93 } 94 95 // Notify causes package signal to relay incoming signals to c. 96 // If no signals are provided, all incoming signals will be relayed to c. 97 // Otherwise, just the provided signals will. 98 // 99 // Package signal will not block sending to c: the caller must ensure 100 // that c has sufficient buffer space to keep up with the expected 101 // signal rate. For a channel used for notification of just one signal value, 102 // a buffer of size 1 is sufficient. 103 // 104 // It is allowed to call Notify multiple times with the same channel: 105 // each call expands the set of signals sent to that channel. 106 // The only way to remove signals from the set is to call Stop. 107 // 108 // It is allowed to call Notify multiple times with different channels 109 // and the same signals: each channel receives copies of incoming 110 // signals independently. 111 func Notify(c chan<- os.Signal, sig ...os.Signal) { 112 if c == nil { 113 panic("os/signal: Notify using nil channel") 114 } 115 116 handlers.Lock() 117 defer handlers.Unlock() 118 119 h := handlers.m[c] 120 if h == nil { 121 if handlers.m == nil { 122 handlers.m = make(map[chan<- os.Signal]*handler) 123 } 124 h = new(handler) 125 handlers.m[c] = h 126 } 127 128 add := func(n int) { 129 if n < 0 { 130 return 131 } 132 if !h.want(n) { 133 h.set(n) 134 if handlers.ref[n] == 0 { 135 enableSignal(n) 136 } 137 handlers.ref[n]++ 138 } 139 } 140 141 if len(sig) == 0 { 142 for n := 0; n < numSig; n++ { 143 add(n) 144 } 145 } else { 146 for _, s := range sig { 147 add(signum(s)) 148 } 149 } 150 } 151 152 // Reset undoes the effect of any prior calls to Notify for the provided 153 // signals. 154 // If no signals are provided, all signal handlers will be reset. 155 func Reset(sig ...os.Signal) { 156 cancel(sig, disableSignal) 157 } 158 159 // Stop causes package signal to stop relaying incoming signals to c. 160 // It undoes the effect of all prior calls to Notify using c. 161 // When Stop returns, it is guaranteed that c will receive no more signals. 162 func Stop(c chan<- os.Signal) { 163 handlers.Lock() 164 165 h := handlers.m[c] 166 if h == nil { 167 handlers.Unlock() 168 return 169 } 170 delete(handlers.m, c) 171 172 for n := 0; n < numSig; n++ { 173 if h.want(n) { 174 handlers.ref[n]-- 175 if handlers.ref[n] == 0 { 176 disableSignal(n) 177 } 178 } 179 } 180 181 // Signals will no longer be delivered to the channel. 182 // We want to avoid a race for a signal such as SIGINT: 183 // it should be either delivered to the channel, 184 // or the program should take the default action (that is, exit). 185 // To avoid the possibility that the signal is delivered, 186 // and the signal handler invoked, and then Stop deregisters 187 // the channel before the process function below has a chance 188 // to send it on the channel, put the channel on a list of 189 // channels being stopped and wait for signal delivery to 190 // quiesce before fully removing it. 191 192 handlers.stopping = append(handlers.stopping, stopping{c, h}) 193 194 handlers.Unlock() 195 196 signalWaitUntilIdle() 197 198 handlers.Lock() 199 200 for i, s := range handlers.stopping { 201 if s.c == c { 202 handlers.stopping = append(handlers.stopping[:i], handlers.stopping[i+1:]...) 203 break 204 } 205 } 206 207 handlers.Unlock() 208 } 209 210 // Wait until there are no more signals waiting to be delivered. 211 // Defined by the runtime package. 212 func signalWaitUntilIdle() 213 214 func process(sig os.Signal) { 215 n := signum(sig) 216 if n < 0 { 217 return 218 } 219 220 handlers.Lock() 221 defer handlers.Unlock() 222 223 for c, h := range handlers.m { 224 if h.want(n) { 225 // send but do not block for it 226 select { 227 case c <- sig: 228 default: 229 } 230 } 231 } 232 233 // Avoid the race mentioned in Stop. 234 for _, d := range handlers.stopping { 235 if d.h.want(n) { 236 select { 237 case d.c <- sig: 238 default: 239 } 240 } 241 } 242 }