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 module ocean.sys.SignalMask; 27 28 import core.sys.posix.signal; 29 30 debug ( SignalMask ) import ocean.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 public struct SignalSet 45 { 46 /*************************************************************************** 47 48 Signal set. 49 50 ***************************************************************************/ 51 52 private sigset_t sigset; 53 54 55 /*************************************************************************** 56 57 Clears all signals in the set (i.e. sets to the set of no signals). 58 59 ***************************************************************************/ 60 61 public void clear ( ) 62 { 63 sigemptyset(&(&this).sigset); 64 } 65 66 67 /*************************************************************************** 68 69 Sets to the set of all signals. 70 71 ***************************************************************************/ 72 73 public void setAll ( ) 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 public void remove ( int signal ) 91 { 92 sigdelset(&(&this).sigset, signal); 93 } 94 95 public alias remove opSub; 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 public void add ( int signal ) 110 { 111 sigaddset(&(&this).sigset, signal); 112 } 113 114 public alias add opAdd; 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 public void remove ( in int[] signals ) 129 { 130 foreach ( signal; signals ) 131 { 132 (&this).remove(signal); 133 } 134 } 135 136 public alias remove opSub; 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 public void add ( in int[] signals ) 151 { 152 foreach ( signal; signals ) 153 { 154 (&this).add(signal); 155 } 156 } 157 158 public alias add opAdd; 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 public bool isSet ( int signal ) 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 public typeof(this) mask ( int how = SIG_SETMASK ) 205 in 206 { 207 switch (how) 208 { 209 case SIG_SETMASK, SIG_BLOCK, SIG_UNBLOCK: 210 break; 211 212 default: 213 assert(false, "invalid pthread_sigmask opcode"); 214 } 215 } 216 body 217 { 218 typeof(this) old_set; 219 220 pthread_sigmask(how, &(&this).sigset, &old_set.sigset); 221 222 return old_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 public typeof(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 public typeof(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 public void callBlocked ( lazy void op ) 270 { 271 auto old_sigset = (&this).block(); 272 273 scope ( exit ) 274 { 275 debug ( SignalMask ) 276 { 277 sigset_t pending; 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 public static typeof(this) getCurrent ( ) 305 { 306 typeof(this) current_set; 307 308 pthread_sigmask(SIG_SETMASK, null, ¤t_set.sigset); 309 310 return current_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 public sigset_t opCast ( ) 321 { 322 return (&this).sigset; 323 } 324 }