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

Diff of /smsdaemon/serialport/PosixSignalDispatcher.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.195  
changed lines
  Added in v.196

  ViewVC Help
Powered by ViewVC 1.1.20