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 /*************************************************************************** 96 97 Adds the specified signal to the set. 98 99 Params: 100 signal = signal to add to set 101 102 This method is aliased as opAdd. 103 104 ***************************************************************************/ 105 106 public void add ( int signal ) 107 { 108 sigaddset(&this.sigset, signal); 109 } 110 111 /*************************************************************************** 112 113 Removes the specified signals from the set. 114 115 Params: 116 signals = signals to remove from set 117 118 This method is aliased as opSub. 119 120 ***************************************************************************/ 121 122 public void remove ( in int[] signals ) 123 { 124 foreach ( signal; signals ) 125 { 126 this.remove(signal); 127 } 128 } 129 130 /*************************************************************************** 131 132 Adds the specified signals to the set. 133 134 Params: 135 signals = signals to add to set 136 137 This method is aliased as opAdd. 138 139 ***************************************************************************/ 140 141 public void add ( in int[] signals ) 142 { 143 foreach ( signal; signals ) 144 { 145 this.add(signal); 146 } 147 } 148 149 /*************************************************************************** 150 151 Tells whether a signal is in the set. 152 153 Params: 154 signal = signal to test 155 156 Returns: 157 true if signal is in set 158 159 ***************************************************************************/ 160 161 public bool isSet ( int signal ) 162 { 163 return !!sigismember(&this.sigset, signal); 164 } 165 166 /*************************************************************************** 167 168 Calls pthread_sigmask() with the set of signals of this instance. 169 170 Params: 171 how = specifies the operation of pthread_sigmask(): 172 SIG_SETMASK: All signals in the set of this instance this set 173 will be blocked, and all other signals will be unblocked. 174 SIG_BLOCK: All signals in the set of this instance this set 175 will be blocked, and the blocking status of all other 176 signals will remain unchanged. 177 SIG_UNBLOCK: All signals in the set of this instance this set 178 will be unblocked, and the blocking status of all other 179 signals will remain unchanged. 180 181 Returns: 182 previous masked signals set (call its sigmask() method to restore 183 the previous state) 184 185 In: 186 how must be SIG_SETMASK, SIG_BLOCK or SIG_UNBLOCK. Note that 187 ensuring this guarantees that pthread_sigmask() will always 188 succeed. 189 190 ***************************************************************************/ 191 192 public typeof(this) mask ( int how = SIG_SETMASK ) 193 in 194 { 195 switch (how) 196 { 197 case SIG_SETMASK, SIG_BLOCK, SIG_UNBLOCK: 198 break; 199 200 default: 201 assert(false, "invalid pthread_sigmask opcode"); 202 } 203 } 204 do 205 { 206 typeof(this) old_set; 207 208 pthread_sigmask(how, &this.sigset, &old_set.sigset); 209 210 return old_set; 211 } 212 213 /*************************************************************************** 214 215 Blocks the signals in in the set of this instance in the calling thread. 216 Signals that are not in this set but are already blocked will stay 217 blocked. 218 219 Returns: 220 previous masked signals set (call its mask() method to restore the 221 previous state) 222 223 ***************************************************************************/ 224 225 public typeof(this) block ( ) 226 { 227 return this.mask(SIG_BLOCK); 228 } 229 230 /*************************************************************************** 231 232 Unblocks the signals in in the set of this instance in the calling 233 thread. Signals that are not in this set but are not blocked will stay 234 unblocked. 235 236 Returns: 237 previous masked signals set (call its mask() method to restore the 238 previous state) 239 240 ***************************************************************************/ 241 242 public typeof(this) unblock ( ) 243 { 244 return this.mask(SIG_UNBLOCK); 245 } 246 247 /*************************************************************************** 248 249 Executes op with the signals in this set blocked. The signals are 250 automatically unblocked again after op has finished (returned or threw). 251 252 Params: 253 op = the operation to execute 254 255 ***************************************************************************/ 256 257 public void callBlocked ( lazy void op ) 258 { 259 auto old_sigset = this.block(); 260 261 scope ( exit ) 262 { 263 debug ( SignalMask ) 264 { 265 sigset_t pending; 266 sigpending(&pending); 267 268 foreach ( signal; this.signals ) 269 { 270 if ( sigismember(&pending, signal) ) 271 { 272 Stderr.formatln("Signal {} fired while masked", signal); 273 } 274 } 275 } 276 277 old_sigset.mask(); 278 } 279 280 op; 281 } 282 283 /*************************************************************************** 284 285 Gets the signal mask for the calling thread. 286 287 Returns: 288 set of currently masked signals for the calling thread 289 290 ***************************************************************************/ 291 292 public static typeof(this) getCurrent ( ) 293 { 294 typeof(this) current_set; 295 296 pthread_sigmask(SIG_SETMASK, null, ¤t_set.sigset); 297 298 return current_set; 299 } 300 301 /*************************************************************************** 302 303 Cast operator for convenient use of this struct in C functions which 304 accept a sigset_t. 305 306 ***************************************************************************/ 307 308 public sigset_t opCast ( ) 309 { 310 return this.sigset; 311 } 312 }