/[projects]/smsdaemon/serialport/PosixSignalDispatcher.cpp
ViewVC logotype

Contents of /smsdaemon/serialport/PosixSignalDispatcher.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 196 - (show annotations) (download)
Thu Dec 18 06:53:29 2008 UTC (15 years, 5 months ago) by torben
File size: 8367 byte(s)
Make pretty

astyle -t -b -N

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

  ViewVC Help
Powered by ViewVC 1.1.20