...
Source file src/pkg/os/signal/signal.go
1
2
3
4
5 package signal
6
7 import (
8 "os"
9 "sync"
10 )
11
12 var handlers struct {
13 sync.Mutex
14
15 m map[chan<- os.Signal]*handler
16
17 ref [numSig]int64
18
19
20
21
22
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
48
49
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
82
83
84
85 func Ignore(sig ...os.Signal) {
86 cancel(sig, ignoreSignal)
87 }
88
89
90 func Ignored(sig os.Signal) bool {
91 sn := signum(sig)
92 return sn >= 0 && signalIgnored(sn)
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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
153
154
155 func Reset(sig ...os.Signal) {
156 cancel(sig, disableSignal)
157 }
158
159
160
161
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
182
183
184
185
186
187
188
189
190
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
211
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
226 select {
227 case c <- sig:
228 default:
229 }
230 }
231 }
232
233
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 }
243
View as plain text