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 import ocean.core.Verify; 37 import ocean.io.select.client.model.ISelectClient; 38 import ocean.sys.SignalFD; 39 40 41 /******************************************************************************* 42 43 Signal select event class. 44 45 *******************************************************************************/ 46 47 public class SignalEvent : ISelectClient 48 { 49 /*************************************************************************** 50 51 Alias for signalfd_siginfo. 52 53 ***************************************************************************/ 54 55 public alias SignalFD.SignalInfo SignalInfo; 56 57 58 /*************************************************************************** 59 60 Signal event. 61 62 ***************************************************************************/ 63 64 private SignalFD event; 65 66 67 /*************************************************************************** 68 69 Signal handler delegate. 70 71 ***************************************************************************/ 72 73 private alias void delegate ( SignalInfo siginfo ) Handler; 74 75 private Handler handler; 76 77 78 /*************************************************************************** 79 80 Re-usable array of info about signals which fired. 81 82 ***************************************************************************/ 83 84 private SignalInfo[] siginfos; 85 86 87 /*************************************************************************** 88 89 Constructor. Creates the internal SignalFD instance but does not mask 90 the standard handling of the specified signals. When this client is 91 registered with epoll, the signals are masked. 92 93 The list of signals handled may be extended after construction by 94 calling the register() method. 95 96 Params: 97 handler = delegate to call when a signal fires (must be non-null) 98 signals = list of signals to handle 99 100 Throws: 101 SignalErrnoException if the creation of the SignalFD fails 102 103 ***************************************************************************/ 104 105 public this ( scope Handler handler, int[] signals ... ) 106 { 107 verify(handler !is null); 108 109 this.handler = handler; 110 111 this.event = new SignalFD(signals, false); 112 } 113 114 115 /*************************************************************************** 116 117 Adds the specified signal to the set of signals handled by this client. 118 119 Params: 120 signal = signal to handle 121 122 Returns: 123 this instance for chaining 124 125 Throws: 126 SignalErrnoException if the updating of the SignalFD fails 127 128 ***************************************************************************/ 129 130 public typeof(this) register ( int signal ) 131 { 132 this.event.register(signal, false); 133 134 return this; 135 } 136 137 138 /*************************************************************************** 139 140 Returns: 141 the epoll events to register for. 142 143 ***************************************************************************/ 144 145 public override Event events ( ) 146 { 147 return Event.EPOLLIN; 148 } 149 150 151 /*************************************************************************** 152 153 Required by ISelectable interface. 154 155 Returns: 156 file descriptor used to manage signal event 157 158 ***************************************************************************/ 159 160 public override Handle fileHandle ( ) 161 { 162 return this.event.fileHandle; 163 } 164 165 166 /*************************************************************************** 167 168 Checks whether the specified signal is registered to be handled by this 169 client. 170 171 Params: 172 signal = code of signal to check 173 174 Returns: 175 true if the specified signal is handled by this client 176 177 ***************************************************************************/ 178 179 public bool isRegistered ( int signal ) 180 { 181 return this.event.isRegistered(signal); 182 } 183 184 185 /*************************************************************************** 186 187 Handles events which occurred for the signal event fd. 188 189 (Implements an abstract super class method.) 190 191 Returns: 192 always true, to leave event registered with epoll 193 194 ***************************************************************************/ 195 196 public override bool handle ( Event events ) 197 { 198 this.event.handle(this.siginfos); 199 200 foreach ( siginfo; this.siginfos ) 201 { 202 this.handler(siginfo); 203 } 204 205 return true; 206 } 207 208 209 /*************************************************************************** 210 211 Register method, called after this client is registered with the 212 SelectDispatcher. 213 214 Masks signals handled by this event, meaning that the default signal 215 (interrupt) handler will not deal with them from now. 216 217 ***************************************************************************/ 218 219 protected override void registered_ ( ) 220 { 221 this.event.maskHandledSignals(); 222 } 223 224 225 /*************************************************************************** 226 227 Unregister method, called after this client is unregistered from the 228 SelectDispatcher. 229 230 Unmasks signals handled by this event, meaning that the default signal 231 (interrupt) handler will deal with them from now. 232 233 ***************************************************************************/ 234 235 protected override void unregistered_ ( ) 236 { 237 this.event.unmaskHandledSignals(); 238 } 239 }