1 /*******************************************************************************
2 3 Posix functions for masking & unmasking signals.
4 5 Masked signals will not be noted but will not fire. If a signal occurs one
6 or more times while masked, when it is unmasked it will fire immediately.
7 Signals are not queued, so if a signal fires multiple times while masked, it
8 will only fire once upon unmasking.
9 10 The list of posix signals is defined in ocean.stdc.posix.signal
11 12 Build flags:
13 -debug=SignalMask: prints debugging information to Stderr
14 15 Copyright:
16 Copyright (c) 2009-2016 dunnhumby Germany GmbH.
17 All rights reserved.
18 19 License:
20 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
21 Alternatively, this file may be distributed under the terms of the Tango
22 3-Clause BSD License (see LICENSE_BSD.txt for details).
23 24 *******************************************************************************/25 26 moduleocean.sys.SignalMask;
27 28 importcore.sys.posix.signal;
29 30 debug ( SignalMask ) importocean.io.Stdout : Stderr;
31 32 33 34 /*******************************************************************************
35 36 Signal set struct wrapping the C sigset_t and its setter / getter functions.
37 38 Note that, as this is a struct rather than a class, and thus has no
39 constructor, it is necessary to explicitly call the clear() method before
40 using an instance.
41 42 *******************************************************************************/43 44 publicstructSignalSet45 {
46 /***************************************************************************
47 48 Signal set.
49 50 ***************************************************************************/51 52 privatesigset_tsigset;
53 54 55 /***************************************************************************
56 57 Clears all signals in the set (i.e. sets to the set of no signals).
58 59 ***************************************************************************/60 61 publicvoidclear ( )
62 {
63 sigemptyset(&(&this).sigset);
64 }
65 66 67 /***************************************************************************
68 69 Sets to the set of all signals.
70 71 ***************************************************************************/72 73 publicvoidsetAll ( )
74 {
75 sigfillset(&(&this).sigset);
76 }
77 78 79 /***************************************************************************
80 81 Removes the specified signal from the set.
82 83 Params:
84 signal = signal to remove from set
85 86 This method is aliased as opSub.
87 88 ***************************************************************************/89 90 publicvoidremove ( intsignal )
91 {
92 sigdelset(&(&this).sigset, signal);
93 }
94 95 publicaliasremoveopSub;
96 97 98 /***************************************************************************
99 100 Adds the specified signal to the set.
101 102 Params:
103 signal = signal to add to set
104 105 This method is aliased as opAdd.
106 107 ***************************************************************************/108 109 publicvoidadd ( intsignal )
110 {
111 sigaddset(&(&this).sigset, signal);
112 }
113 114 publicaliasaddopAdd;
115 116 117 /***************************************************************************
118 119 Removes the specified signals from the set.
120 121 Params:
122 signals = signals to remove from set
123 124 This method is aliased as opSub.
125 126 ***************************************************************************/127 128 publicvoidremove ( inint[] signals )
129 {
130 foreach ( signal; signals )
131 {
132 (&this).remove(signal);
133 }
134 }
135 136 publicaliasremoveopSub;
137 138 139 /***************************************************************************
140 141 Adds the specified signals to the set.
142 143 Params:
144 signals = signals to add to set
145 146 This method is aliased as opAdd.
147 148 ***************************************************************************/149 150 publicvoidadd ( inint[] signals )
151 {
152 foreach ( signal; signals )
153 {
154 (&this).add(signal);
155 }
156 }
157 158 publicaliasaddopAdd;
159 160 161 /***************************************************************************
162 163 Tells whether a signal is in the set.
164 165 Params:
166 signal = signal to test
167 168 Returns:
169 true if signal is in set
170 171 ***************************************************************************/172 173 publicboolisSet ( intsignal )
174 {
175 return !!sigismember(&(&this).sigset, signal);
176 }
177 178 /***************************************************************************
179 180 Calls pthread_sigmask() with the set of signals of this instance.
181 182 Params:
183 how = specifies the operation of pthread_sigmask():
184 SIG_SETMASK: All signals in the set of this instance this set
185 will be blocked, and all other signals will be unblocked.
186 SIG_BLOCK: All signals in the set of this instance this set
187 will be blocked, and the blocking status of all other
188 signals will remain unchanged.
189 SIG_UNBLOCK: All signals in the set of this instance this set
190 will be unblocked, and the blocking status of all other
191 signals will remain unchanged.
192 193 Returns:
194 previous masked signals set (call its sigmask() method to restore
195 the previous state)
196 197 In:
198 how must be SIG_SETMASK, SIG_BLOCK or SIG_UNBLOCK. Note that
199 ensuring this guarantees that pthread_sigmask() will always
200 succeed.
201 202 ***************************************************************************/203 204 publictypeof(this) mask ( inthow = SIG_SETMASK )
205 in206 {
207 switch (how)
208 {
209 caseSIG_SETMASK, SIG_BLOCK, SIG_UNBLOCK:
210 break;
211 212 default:
213 assert(false, "invalid pthread_sigmask opcode");
214 }
215 }
216 body217 {
218 typeof(this) old_set;
219 220 pthread_sigmask(how, &(&this).sigset, &old_set.sigset);
221 222 returnold_set;
223 }
224 225 /***************************************************************************
226 227 Blocks the signals in in the set of this instance in the calling thread.
228 Signals that are not in this set but are already blocked will stay
229 blocked.
230 231 Returns:
232 previous masked signals set (call its mask() method to restore the
233 previous state)
234 235 ***************************************************************************/236 237 publictypeof(this) block ( )
238 {
239 return (&this).mask(SIG_BLOCK);
240 }
241 242 /***************************************************************************
243 244 Unblocks the signals in in the set of this instance in the calling
245 thread. Signals that are not in this set but are not blocked will stay
246 unblocked.
247 248 Returns:
249 previous masked signals set (call its mask() method to restore the
250 previous state)
251 252 ***************************************************************************/253 254 publictypeof(this) unblock ( )
255 {
256 return (&this).mask(SIG_UNBLOCK);
257 }
258 259 /***************************************************************************
260 261 Executes op with the signals in this set blocked. The signals are
262 automatically unblocked again after op has finished (returned or threw).
263 264 Params:
265 op = the operation to execute
266 267 ***************************************************************************/268 269 publicvoidcallBlocked ( lazyvoidop )
270 {
271 autoold_sigset = (&this).block();
272 273 scope ( exit )
274 {
275 debug ( SignalMask )
276 {
277 sigset_tpending;
278 sigpending(&pending);
279 280 foreach ( signal; (&this).signals )
281 {
282 if ( sigismember(&pending, signal) )
283 {
284 Stderr.formatln("Signal {} fired while masked", signal);
285 }
286 }
287 }
288 289 old_sigset.mask();
290 }
291 292 op;
293 }
294 295 /***************************************************************************
296 297 Gets the signal mask for the calling thread.
298 299 Returns:
300 set of currently masked signals for the calling thread
301 302 ***************************************************************************/303 304 publicstatictypeof(this) getCurrent ( )
305 {
306 typeof(this) current_set;
307 308 pthread_sigmask(SIG_SETMASK, null, ¤t_set.sigset);
309 310 returncurrent_set;
311 }
312 313 /***************************************************************************
314 315 Cast operator for convenient use of this struct in C functions which
316 accept a sigset_t.
317 318 ***************************************************************************/319 320 publicsigset_topCast ( )
321 {
322 return (&this).sigset;
323 }
324 }