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

Annotation of /smsdaemon/serialport/PosixSignalDispatcher.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 114 - (hide annotations) (download)
Sun Nov 2 20:14:20 2008 UTC (15 years, 7 months ago) by torben
File size: 9861 byte(s)
Enable compilation 4.3

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     /**
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