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

Annotation of /smsdaemon/serialport/PosixSignalDispatcher.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 91 - (hide annotations) (download)
Mon Jun 16 10:56:02 2008 UTC (15 years, 11 months ago) by torben
File size: 9821 byte(s)
Move serialport to its own directory

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