1 /******************************************************************************* 2 3 Linux signal file descriptor event for use with epoll. 4 5 Allows signals to be handled as events in epoll, rather than as interrupts. 6 One or more signals can be specified. Once the SignalEvent is registered, 7 the default interrupt-based signal handlers will no longer receive these 8 events, and they will cause this select client's event to fire in epoll 9 instead. When the fired event is handled, a user-provided delegate is 10 called, which receives a SignalInfo struct (see ocean.sys.SignalFD) 11 providing information about the signal which fired. 12 13 Note that when the SignalEvent is unregistered from epoll, the interrupt- 14 based signal handlers are automatically reinstated. 15 16 Warning: signalfd behaves poorly in multi-threaded programs, (including 17 programs using third party libraries which use threads internally). 18 SignalEvents are triggered only if signals are masked in all threads. 19 Ensuring that this condition is met is often impossible, particularly if 20 threads are created inside third-party libraries. For this reason it is 21 generally more reliable to use a signal handler rather than a SignalEvent. 22 23 Copyright: 24 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 25 All rights reserved. 26 27 License: 28 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 29 Alternatively, this file may be distributed under the terms of the Tango 30 3-Clause BSD License (see LICENSE_BSD.txt for details). 31 32 *******************************************************************************/ 33 34 module ocean.io.select.client.SignalEvent; 35 36 37 38 39 import ocean.core.Verify; 40 41 import ocean.io.select.client.model.ISelectClient; 42 43 import ocean.sys.SignalFD; 44 45 46 47 48 /******************************************************************************* 49 50 Signal select event class. 51 52 *******************************************************************************/ 53 54 public class SignalEvent : ISelectClient 55 { 56 /*************************************************************************** 57 58 Alias for signalfd_siginfo. 59 60 ***************************************************************************/ 61 62 public alias SignalFD.SignalInfo SignalInfo; 63 64 65 /*************************************************************************** 66 67 Signal event. 68 69 ***************************************************************************/ 70 71 private SignalFD event; 72 73 74 /*************************************************************************** 75 76 Signal handler delegate. 77 78 ***************************************************************************/ 79 80 private alias void delegate ( SignalInfo siginfo ) Handler; 81 82 private Handler handler; 83 84 85 /*************************************************************************** 86 87 Re-usable array of info about signals which fired. 88 89 ***************************************************************************/ 90 91 private SignalInfo[] siginfos; 92 93 94 /*************************************************************************** 95 96 Constructor. Creates the internal SignalFD instance but does not mask 97 the standard handling of the specified signals. When this client is 98 registered with epoll, the signals are masked. 99 100 The list of signals handled may be extended after construction by 101 calling the register() method. 102 103 Params: 104 handler = delegate to call when a signal fires (must be non-null) 105 signals = list of signals to handle 106 107 Throws: 108 SignalErrnoException if the creation of the SignalFD fails 109 110 ***************************************************************************/ 111 112 public this ( scope Handler handler, int[] signals ... ) 113 { 114 verify(handler !is null); 115 116 this.handler = handler; 117 118 this.event = new SignalFD(signals, false); 119 } 120 121 122 /*************************************************************************** 123 124 Adds the specified signal to the set of signals handled by this client. 125 126 Params: 127 signal = signal to handle 128 129 Returns: 130 this instance for chaining 131 132 Throws: 133 SignalErrnoException if the updating of the SignalFD fails 134 135 ***************************************************************************/ 136 137 public typeof(this) register ( int signal ) 138 { 139 this.event.register(signal, false); 140 141 return this; 142 } 143 144 145 /*************************************************************************** 146 147 Returns: 148 the epoll events to register for. 149 150 ***************************************************************************/ 151 152 public override Event events ( ) 153 { 154 return Event.EPOLLIN; 155 } 156 157 158 /*************************************************************************** 159 160 Required by ISelectable interface. 161 162 Returns: 163 file descriptor used to manage signal event 164 165 ***************************************************************************/ 166 167 public override Handle fileHandle ( ) 168 { 169 return this.event.fileHandle; 170 } 171 172 173 /*************************************************************************** 174 175 Checks whether the specified signal is registered to be handled by this 176 client. 177 178 Params: 179 signal = code of signal to check 180 181 Returns: 182 true if the specified signal is handled by this client 183 184 ***************************************************************************/ 185 186 public bool isRegistered ( int signal ) 187 { 188 return this.event.isRegistered(signal); 189 } 190 191 192 /*************************************************************************** 193 194 Handles events which occurred for the signal event fd. 195 196 (Implements an abstract super class method.) 197 198 Returns: 199 always true, to leave event registered with epoll 200 201 ***************************************************************************/ 202 203 public override bool handle ( Event events ) 204 { 205 this.event.handle(this.siginfos); 206 207 foreach ( siginfo; this.siginfos ) 208 { 209 this.handler(siginfo); 210 } 211 212 return true; 213 } 214 215 216 /*************************************************************************** 217 218 Register method, called after this client is registered with the 219 SelectDispatcher. 220 221 Masks signals handled by this event, meaning that the default signal 222 (interrupt) handler will not deal with them from now. 223 224 ***************************************************************************/ 225 226 protected override void registered_ ( ) 227 { 228 this.event.maskHandledSignals(); 229 } 230 231 232 /*************************************************************************** 233 234 Unregister method, called after this client is unregistered from the 235 SelectDispatcher. 236 237 Unmasks signals handled by this event, meaning that the default signal 238 (interrupt) handler will deal with them from now. 239 240 ***************************************************************************/ 241 242 protected override void unregistered_ ( ) 243 { 244 this.event.unmaskHandledSignals(); 245 } 246 } 247