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

Contents of /smsdaemon/PosixSignalDispatcher.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show annotations) (download)
Mon Jun 9 18:15:53 2008 UTC (15 years, 11 months ago) by torben
File size: 9821 byte(s)
Added first basic edition of smsdaemon.

So far sending & receiving sms works and a basic sample plugin is implemented.

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

  ViewVC Help
Powered by ViewVC 1.1.20