14 |
#include <map> |
#include <map> |
15 |
#include <errno.h> |
#include <errno.h> |
16 |
#include <signal.h> |
#include <signal.h> |
17 |
|
#include <stdlib.h> |
18 |
|
#include <string.h> |
19 |
|
|
20 |
namespace |
namespace |
21 |
{ |
{ |
22 |
/** |
/** |
23 |
* Implementation class for the PosixSignalDispatcher. |
* Implementation class for the PosixSignalDispatcher. |
24 |
*/ |
*/ |
25 |
class PosixSignalDispatcherImpl |
class PosixSignalDispatcherImpl |
26 |
{ |
{ |
27 |
public: |
public: |
28 |
/* |
/* |
29 |
* As in the case of PosixSignalDispatcher, this is also |
* As in the case of PosixSignalDispatcher, this is also |
30 |
* a singleton class. The only instance of this class can |
* a singleton class. The only instance of this class can |
31 |
* be obtained using this method. |
* be obtained using this method. |
32 |
*/ |
*/ |
33 |
static |
static |
34 |
PosixSignalDispatcherImpl& |
PosixSignalDispatcherImpl& |
35 |
Instance() ; |
Instance() ; |
36 |
|
|
37 |
/* |
/* |
38 |
* Implementation of PosixSignalDispatcher::AttachHandler() |
* Implementation of PosixSignalDispatcher::AttachHandler() |
39 |
*/ |
*/ |
40 |
void |
void |
41 |
AttachHandler( const int posixSignalNumber, |
AttachHandler( const int posixSignalNumber, |
42 |
PosixSignalHandler& signalHandler ) |
PosixSignalHandler& signalHandler ) |
43 |
throw( PosixSignalDispatcher::CannotAttachHandler ) ; |
throw( PosixSignalDispatcher::CannotAttachHandler ) ; |
44 |
|
|
45 |
/* |
/* |
46 |
* Implementation of PosixSignalDispatcher::DetachHandler() |
* Implementation of PosixSignalDispatcher::DetachHandler() |
47 |
*/ |
*/ |
48 |
void |
void |
49 |
DetachHandler( const int posixSignalNumber, |
DetachHandler( const int posixSignalNumber, |
50 |
const PosixSignalHandler& signalHandler ) |
const PosixSignalHandler& signalHandler ) |
51 |
throw( PosixSignalDispatcher::CannotDetachHandler, |
throw( PosixSignalDispatcher::CannotDetachHandler, |
52 |
std::logic_error ) ; |
std::logic_error ) ; |
53 |
private: |
private: |
54 |
/* |
/* |
55 |
* List of signal handlers that are currently associated |
* List of signal handlers that are currently associated |
56 |
* with the dispatcher. |
* with the dispatcher. |
57 |
*/ |
*/ |
58 |
typedef std::multimap<int, PosixSignalHandler*> SignalHandlerList ; |
typedef std::multimap<int, PosixSignalHandler*> SignalHandlerList ; |
59 |
static SignalHandlerList mSignalHandlerList ; |
static SignalHandlerList mSignalHandlerList ; |
60 |
|
|
61 |
/* |
/* |
62 |
* List of signal handlers that were originally attached |
* List of signal handlers that were originally attached |
63 |
* to the corresponding signals. |
* to the corresponding signals. |
64 |
*/ |
*/ |
65 |
typedef std::map<int, struct sigaction> OriginalSigactionList ; |
typedef std::map<int, struct sigaction> OriginalSigactionList ; |
66 |
static OriginalSigactionList mOriginalSigactionList ; |
static OriginalSigactionList mOriginalSigactionList ; |
67 |
|
|
68 |
/* |
/* |
69 |
* Default constructor. |
* Default constructor. |
70 |
*/ |
*/ |
71 |
PosixSignalDispatcherImpl() ; |
PosixSignalDispatcherImpl() ; |
72 |
|
|
73 |
/* |
/* |
74 |
* Destuctor. |
* Destuctor. |
75 |
*/ |
*/ |
76 |
~PosixSignalDispatcherImpl() ; |
~PosixSignalDispatcherImpl() ; |
77 |
|
|
78 |
/* |
/* |
79 |
* Static function that is used to attach the signal |
* Static function that is used to attach the signal |
80 |
* dispatcher to a signal using sigaction(). |
* dispatcher to a signal using sigaction(). |
81 |
*/ |
*/ |
82 |
static |
static |
83 |
void |
void |
84 |
SigactionHandler( int signalNumber ) ; |
SigactionHandler( int signalNumber ) ; |
85 |
} ; |
} ; |
86 |
|
|
87 |
// |
// |
88 |
// Initialization of static members of class PosixSignalDispatcherImpl. |
// Initialization of static members of class PosixSignalDispatcherImpl. |
89 |
// |
// |
90 |
PosixSignalDispatcherImpl::SignalHandlerList |
PosixSignalDispatcherImpl::SignalHandlerList |
91 |
PosixSignalDispatcherImpl::mSignalHandlerList ; |
PosixSignalDispatcherImpl::mSignalHandlerList ; |
92 |
|
|
93 |
PosixSignalDispatcherImpl::OriginalSigactionList |
PosixSignalDispatcherImpl::OriginalSigactionList |
94 |
PosixSignalDispatcherImpl::mOriginalSigactionList ; |
PosixSignalDispatcherImpl::mOriginalSigactionList ; |
95 |
|
|
96 |
} ; |
} ; |
97 |
|
|
98 |
PosixSignalDispatcher::PosixSignalDispatcher() |
PosixSignalDispatcher::PosixSignalDispatcher() |
99 |
{ |
{ |
100 |
/* empty */ |
/* empty */ |
101 |
} |
} |
102 |
|
|
103 |
PosixSignalDispatcher::~PosixSignalDispatcher() |
PosixSignalDispatcher::~PosixSignalDispatcher() |
104 |
{ |
{ |
105 |
/* empty */ |
/* empty */ |
106 |
} |
} |
107 |
|
|
108 |
PosixSignalDispatcher& |
PosixSignalDispatcher& |
109 |
PosixSignalDispatcher::Instance() |
PosixSignalDispatcher::Instance() |
110 |
{ |
{ |
111 |
static PosixSignalDispatcher single_instance ; |
static PosixSignalDispatcher single_instance ; |
112 |
return single_instance ; |
return single_instance ; |
113 |
} |
} |
114 |
|
|
115 |
void |
void |
116 |
PosixSignalDispatcher::AttachHandler( const int posixSignalNumber, |
PosixSignalDispatcher::AttachHandler( const int posixSignalNumber, |
117 |
PosixSignalHandler& signalHandler ) |
PosixSignalHandler& signalHandler ) |
118 |
throw( CannotAttachHandler ) |
throw( CannotAttachHandler ) |
119 |
{ |
{ |
120 |
PosixSignalDispatcherImpl::Instance().AttachHandler( posixSignalNumber, |
PosixSignalDispatcherImpl::Instance().AttachHandler( posixSignalNumber, |
121 |
signalHandler ) ; |
signalHandler ) ; |
122 |
return ; |
return ; |
123 |
} |
} |
124 |
|
|
125 |
void |
void |
126 |
PosixSignalDispatcher::DetachHandler( const int posixSignalNumber, |
PosixSignalDispatcher::DetachHandler( const int posixSignalNumber, |
127 |
const PosixSignalHandler& signalHandler ) |
const PosixSignalHandler& signalHandler ) |
128 |
throw( CannotDetachHandler, |
throw( CannotDetachHandler, |
129 |
std::logic_error ) |
std::logic_error ) |
130 |
{ |
{ |
131 |
PosixSignalDispatcherImpl::Instance().DetachHandler( posixSignalNumber, |
PosixSignalDispatcherImpl::Instance().DetachHandler( posixSignalNumber, |
132 |
signalHandler ) ; |
signalHandler ) ; |
133 |
} |
} |
134 |
|
|
135 |
namespace |
namespace |
136 |
{ |
{ |
137 |
inline |
inline |
138 |
PosixSignalDispatcherImpl::PosixSignalDispatcherImpl() |
PosixSignalDispatcherImpl::PosixSignalDispatcherImpl() |
139 |
{ |
{ |
140 |
/* empty */ |
/* empty */ |
141 |
} |
} |
142 |
|
|
143 |
inline |
inline |
144 |
PosixSignalDispatcherImpl::~PosixSignalDispatcherImpl() |
PosixSignalDispatcherImpl::~PosixSignalDispatcherImpl() |
145 |
{ |
{ |
146 |
/* empty */ |
/* empty */ |
147 |
} |
} |
148 |
|
|
149 |
inline |
inline |
150 |
PosixSignalDispatcherImpl& |
PosixSignalDispatcherImpl& |
151 |
PosixSignalDispatcherImpl::Instance() |
PosixSignalDispatcherImpl::Instance() |
152 |
{ |
{ |
153 |
static PosixSignalDispatcherImpl single_instance ; |
static PosixSignalDispatcherImpl single_instance ; |
154 |
return single_instance ; |
return single_instance ; |
155 |
} |
} |
156 |
|
|
157 |
inline |
inline |
158 |
void |
void |
159 |
PosixSignalDispatcherImpl::AttachHandler( |
PosixSignalDispatcherImpl::AttachHandler( |
160 |
const int posixSignalNumber, |
const int posixSignalNumber, |
161 |
PosixSignalHandler& signalHandler ) |
PosixSignalHandler& signalHandler ) |
162 |
throw( PosixSignalDispatcher::CannotAttachHandler ) |
throw( PosixSignalDispatcher::CannotAttachHandler ) |
163 |
{ |
{ |
164 |
/* |
/* |
165 |
* Attach this instance of PosixSignalDispatcher to the specified |
* Attach this instance of PosixSignalDispatcher to the specified |
166 |
* signal. |
* signal. |
167 |
*/ |
*/ |
168 |
struct sigaction sigaction_info ; |
struct sigaction sigaction_info ; |
169 |
sigaction_info.sa_handler = PosixSignalDispatcherImpl::SigactionHandler ; |
sigaction_info.sa_handler = PosixSignalDispatcherImpl::SigactionHandler ; |
170 |
sigemptyset( &sigaction_info.sa_mask ) ; |
sigemptyset( &sigaction_info.sa_mask ) ; |
171 |
sigaction_info.sa_flags = 0 ; |
sigaction_info.sa_flags = 0 ; |
172 |
/* |
/* |
173 |
* Install the handler and get a copy of the previous handler. |
* Install the handler and get a copy of the previous handler. |
174 |
*/ |
*/ |
175 |
struct sigaction old_action ; |
struct sigaction old_action ; |
176 |
if ( sigaction( posixSignalNumber, |
if ( sigaction( posixSignalNumber, |
177 |
&sigaction_info, |
&sigaction_info, |
178 |
&old_action ) < 0 ) |
&old_action ) < 0 ) |
179 |
{ |
{ |
180 |
throw PosixSignalDispatcher::CannotAttachHandler( strerror(errno) ) ; |
throw PosixSignalDispatcher::CannotAttachHandler( strerror(errno) ) ; |
181 |
} |
} |
182 |
/* |
/* |
183 |
* Save a copy of the old handler if it is not PosixSignalDispatcher::SignalHandler. |
* Save a copy of the old handler if it is not PosixSignalDispatcher::SignalHandler. |
184 |
*/ |
*/ |
185 |
if ( PosixSignalDispatcherImpl::SigactionHandler != old_action.sa_handler ) |
if ( PosixSignalDispatcherImpl::SigactionHandler != old_action.sa_handler ) |
186 |
{ |
{ |
187 |
mOriginalSigactionList.insert( |
mOriginalSigactionList.insert( |
188 |
OriginalSigactionList::value_type( posixSignalNumber, |
OriginalSigactionList::value_type( posixSignalNumber, |
189 |
old_action ) ) ; |
old_action ) ) ; |
190 |
} |
} |
191 |
/* |
/* |
192 |
* Add the specified handler to the list of handlers associated with the signal. |
* Add the specified handler to the list of handlers associated with the signal. |
193 |
*/ |
*/ |
194 |
mSignalHandlerList.insert( |
mSignalHandlerList.insert( |
195 |
SignalHandlerList::value_type( posixSignalNumber, |
SignalHandlerList::value_type( posixSignalNumber, |
196 |
&signalHandler ) ) ; |
&signalHandler ) ) ; |
197 |
return ; |
return ; |
198 |
} |
} |
199 |
|
|
200 |
inline |
inline |
201 |
void |
void |
202 |
PosixSignalDispatcherImpl::DetachHandler( |
PosixSignalDispatcherImpl::DetachHandler( |
203 |
const int posixSignalNumber, |
const int posixSignalNumber, |
204 |
const PosixSignalHandler& signalHandler ) |
const PosixSignalHandler& signalHandler ) |
205 |
throw( PosixSignalDispatcher::CannotDetachHandler, |
throw( PosixSignalDispatcher::CannotDetachHandler, |
206 |
std::logic_error ) |
std::logic_error ) |
207 |
{ |
{ |
208 |
/* |
/* |
209 |
* Get the range of values in the SignalHandlerList corresponding |
* Get the range of values in the SignalHandlerList corresponding |
210 |
* to the specified signal number. |
* to the specified signal number. |
211 |
*/ |
*/ |
212 |
std::pair<SignalHandlerList::iterator, SignalHandlerList::iterator> |
std::pair<SignalHandlerList::iterator, SignalHandlerList::iterator> |
213 |
iterator_range = mSignalHandlerList.equal_range( posixSignalNumber ) ; |
iterator_range = mSignalHandlerList.equal_range( posixSignalNumber ) ; |
214 |
/* |
/* |
215 |
* Check if signalHandler is attached to the posixSignalNumber signal. |
* Check if signalHandler is attached to the posixSignalNumber signal. |
216 |
*/ |
*/ |
217 |
SignalHandlerList::iterator sig_handler_location = mSignalHandlerList.end() ; |
SignalHandlerList::iterator sig_handler_location = mSignalHandlerList.end() ; |
218 |
for( SignalHandlerList::iterator i=iterator_range.first ; |
for ( SignalHandlerList::iterator i=iterator_range.first ; |
219 |
i != iterator_range.second ; |
i != iterator_range.second ; |
220 |
++i ) |
++i ) |
221 |
{ |
{ |
222 |
if ( i->second == &signalHandler ) |
if ( i->second == &signalHandler ) |
223 |
{ |
{ |
224 |
sig_handler_location = i ; |
sig_handler_location = i ; |
225 |
break ; |
break ; |
226 |
} |
} |
227 |
} |
} |
228 |
/* |
/* |
229 |
* If the signal handler is found, we need to remove it from the list. |
* If the signal handler is found, we need to remove it from the list. |
230 |
*/ |
*/ |
231 |
if ( mSignalHandlerList.end() != sig_handler_location ) |
if ( mSignalHandlerList.end() != sig_handler_location ) |
232 |
{ |
{ |
233 |
mSignalHandlerList.erase( sig_handler_location ) ; |
mSignalHandlerList.erase( sig_handler_location ) ; |
234 |
/* |
/* |
235 |
* If this was the only signal handler associated with the specified |
* If this was the only signal handler associated with the specified |
236 |
* signal number, then we remove the signal dispatcher from handling |
* signal number, then we remove the signal dispatcher from handling |
237 |
* the signal and install the original signal. |
* the signal and install the original signal. |
238 |
*/ |
*/ |
239 |
if ( 0 == mSignalHandlerList.count( posixSignalNumber ) ) |
if ( 0 == mSignalHandlerList.count( posixSignalNumber ) ) |
240 |
{ |
{ |
241 |
/* |
/* |
242 |
* Retrieve the original sigaction corresponding to the signal. |
* Retrieve the original sigaction corresponding to the signal. |
243 |
*/ |
*/ |
244 |
OriginalSigactionList::iterator original_sigaction = |
OriginalSigactionList::iterator original_sigaction = |
245 |
mOriginalSigactionList.find( posixSignalNumber ) ; |
mOriginalSigactionList.find( posixSignalNumber ) ; |
246 |
/* |
/* |
247 |
* If the signal dispatcher implementation is correct, |
* If the signal dispatcher implementation is correct, |
248 |
* then we should always find the original sigaction. |
* then we should always find the original sigaction. |
249 |
* If we do not find one, we throw an exception. |
* If we do not find one, we throw an exception. |
250 |
*/ |
*/ |
251 |
if ( mOriginalSigactionList.end() == original_sigaction ) |
if ( mOriginalSigactionList.end() == original_sigaction ) |
252 |
{ |
{ |
253 |
throw std::logic_error( "Signal dispatcher in invalid state." ) ; |
throw std::logic_error( "Signal dispatcher in invalid state." ) ; |
254 |
} |
} |
255 |
/* |
/* |
256 |
* Install the original handler. Throw an exception if we |
* Install the original handler. Throw an exception if we |
257 |
* encounter any error. |
* encounter any error. |
258 |
*/ |
*/ |
259 |
if ( sigaction( posixSignalNumber, |
if ( sigaction( posixSignalNumber, |
260 |
&original_sigaction->second, |
&original_sigaction->second, |
261 |
NULL ) < 0 ) |
NULL ) < 0 ) |
262 |
{ |
{ |
263 |
throw PosixSignalDispatcher::CannotDetachHandler( strerror(errno) ) ; |
throw PosixSignalDispatcher::CannotDetachHandler( strerror(errno) ) ; |
264 |
} |
} |
265 |
} |
} |
266 |
} |
} |
267 |
return ; |
return ; |
268 |
} |
} |
269 |
|
|
270 |
|
|
271 |
void |
void |
272 |
PosixSignalDispatcherImpl::SigactionHandler( int signalNumber ) |
PosixSignalDispatcherImpl::SigactionHandler( int signalNumber ) |
273 |
{ |
{ |
274 |
/* |
/* |
275 |
* Get a list of handlers associated with signalNumber. |
* Get a list of handlers associated with signalNumber. |
276 |
*/ |
*/ |
277 |
std::pair<SignalHandlerList::iterator, SignalHandlerList::iterator> |
std::pair<SignalHandlerList::iterator, SignalHandlerList::iterator> |
278 |
iterator_range = mSignalHandlerList.equal_range( signalNumber ) ; |
iterator_range = mSignalHandlerList.equal_range( signalNumber ) ; |
279 |
/* |
/* |
280 |
* Call each handler. |
* Call each handler. |
281 |
*/ |
*/ |
282 |
for( SignalHandlerList::iterator i=iterator_range.first ; |
for ( SignalHandlerList::iterator i=iterator_range.first ; |
283 |
i != iterator_range.second ; |
i != iterator_range.second ; |
284 |
++i ) |
++i ) |
285 |
{ |
{ |
286 |
i->second->HandlePosixSignal( signalNumber ) ; |
i->second->HandlePosixSignal( signalNumber ) ; |
287 |
} |
} |
288 |
// |
// |
289 |
// :TODO: Why is the following code commented out using "#if 0" ? |
// :TODO: Why is the following code commented out using "#if 0" ? |
290 |
// Check and remove this code if it is not necessary. Otherwise, if |
// Check and remove this code if it is not necessary. Otherwise, if |
291 |
// it has been commented out due to a bug then debug and correct it. |
// it has been commented out due to a bug then debug and correct it. |
292 |
// |
// |
293 |
#if 0 |
#if 0 |
294 |
/* |
/* |
295 |
* Get the original handler that was associated with the |
* Get the original handler that was associated with the |
296 |
* signal and call it if possible. |
* signal and call it if possible. |
297 |
*/ |
*/ |
298 |
OriginalSigactionList::iterator original_sigaction = |
OriginalSigactionList::iterator original_sigaction = |
299 |
mOriginalSigactionList.find( posixSignalNumber ) ; |
mOriginalSigactionList.find( posixSignalNumber ) ; |
300 |
if ( ( mOriginalSigactionList.end() != original_sigaction ) && |
if ( ( mOriginalSigactionList.end() != original_sigaction ) && |
301 |
( SIG_DFL != original_sigaction->second.sa_handler ) && |
( SIG_DFL != original_sigaction->second.sa_handler ) && |
302 |
( SIG_IGN != original_sigaction->second.sa_handler ) && |
( SIG_IGN != original_sigaction->second.sa_handler ) && |
303 |
( 0 != original_sigaction->second.sa_handler ) ) |
( 0 != original_sigaction->second.sa_handler ) ) |
304 |
{ |
{ |
305 |
original_sigaction->second.sa_handler( signalNumber ) ; |
original_sigaction->second.sa_handler( signalNumber ) ; |
306 |
} |
} |
307 |
#endif |
#endif |
308 |
// |
// |
309 |
return ; |
return ; |
310 |
} |
} |
311 |
} ; |
} ; |