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

Annotation of /smsdaemon/serialport/PosixSignalDispatcher.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 196 - (hide 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 torben 26 //
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 torben 114 #include <stdlib.h>
18     #include <string.h>
19 torben 26
20     namespace
21     {
22 torben 196 /**
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 torben 26
37 torben 196 /*
38     * Implementation of PosixSignalDispatcher::AttachHandler()
39     */
40     void
41     AttachHandler( const int posixSignalNumber,
42     PosixSignalHandler& signalHandler )
43     throw( PosixSignalDispatcher::CannotAttachHandler ) ;
44 torben 26
45 torben 196 /*
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 torben 26
61 torben 196 /*
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 torben 26
68 torben 196 /*
69     * Default constructor.
70     */
71     PosixSignalDispatcherImpl() ;
72 torben 26
73 torben 196 /*
74     * Destuctor.
75     */
76     ~PosixSignalDispatcherImpl() ;
77 torben 26
78 torben 196 /*
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 torben 26
87 torben 196 //
88     // Initialization of static members of class PosixSignalDispatcherImpl.
89     //
90     PosixSignalDispatcherImpl::SignalHandlerList
91     PosixSignalDispatcherImpl::mSignalHandlerList ;
92 torben 26
93 torben 196 PosixSignalDispatcherImpl::OriginalSigactionList
94     PosixSignalDispatcherImpl::mOriginalSigactionList ;
95 torben 26
96     } ;
97    
98     PosixSignalDispatcher::PosixSignalDispatcher()
99     {
100 torben 196 /* empty */
101 torben 26 }
102    
103     PosixSignalDispatcher::~PosixSignalDispatcher()
104     {
105 torben 196 /* empty */
106 torben 26 }
107    
108     PosixSignalDispatcher&
109     PosixSignalDispatcher::Instance()
110     {
111 torben 196 static PosixSignalDispatcher single_instance ;
112     return single_instance ;
113 torben 26 }
114    
115     void
116     PosixSignalDispatcher::AttachHandler( const int posixSignalNumber,
117     PosixSignalHandler& signalHandler )
118 torben 196 throw( CannotAttachHandler )
119 torben 26 {
120 torben 196 PosixSignalDispatcherImpl::Instance().AttachHandler( posixSignalNumber,
121     signalHandler ) ;
122     return ;
123 torben 26 }
124    
125     void
126     PosixSignalDispatcher::DetachHandler( const int posixSignalNumber,
127     const PosixSignalHandler& signalHandler )
128 torben 196 throw( CannotDetachHandler,
129     std::logic_error )
130 torben 26 {
131 torben 196 PosixSignalDispatcherImpl::Instance().DetachHandler( posixSignalNumber,
132     signalHandler ) ;
133 torben 26 }
134    
135     namespace
136     {
137 torben 196 inline
138     PosixSignalDispatcherImpl::PosixSignalDispatcherImpl()
139     {
140     /* empty */
141     }
142 torben 26
143 torben 196 inline
144     PosixSignalDispatcherImpl::~PosixSignalDispatcherImpl()
145     {
146     /* empty */
147     }
148 torben 26
149 torben 196 inline
150     PosixSignalDispatcherImpl&
151     PosixSignalDispatcherImpl::Instance()
152     {
153     static PosixSignalDispatcherImpl single_instance ;
154     return single_instance ;
155     }
156 torben 26
157 torben 196 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 torben 26
200 torben 196 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 torben 26
270    
271 torben 196 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 torben 26 #if 0
294 torben 196 /*
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 torben 26 #endif
308 torben 196 //
309     return ;
310     }
311 torben 26 } ;

  ViewVC Help
Powered by ViewVC 1.1.20