SignalHandler.cxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. /* ====================================================================
  2.  * The Vovida Software License, Version 1.0 
  3.  * 
  4.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  5.  * 
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in
  15.  *    the documentation and/or other materials provided with the
  16.  *    distribution.
  17.  * 
  18.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  19.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  20.  *    not be used to endorse or promote products derived from this
  21.  *    software without prior written permission. For written
  22.  *    permission, please contact vocal@vovida.org.
  23.  *
  24.  * 4. Products derived from this software may not be called "VOCAL", nor
  25.  *    may "VOCAL" appear in their name, without prior written
  26.  *    permission of Vovida Networks, Inc.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  29.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  31.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  32.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  33.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  34.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  35.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  36.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  37.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  39.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  40.  * DAMAGE.
  41.  * 
  42.  * ====================================================================
  43.  * 
  44.  * This software consists of voluntary contributions made by Vovida
  45.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  46.  * Inc.  For more information on Vovida Networks, Inc., please see
  47.  * <http://www.vovida.org/>.
  48.  *
  49.  */
  50. static const char* const SignalHandler_cxx_Version = 
  51.     "$Id: SignalHandler.cxx,v 1.2 2001/04/10 02:12:49 icahoon Exp $";
  52. #include "SignalHandler.hxx"
  53. #include "SignalSet.hxx"
  54. #include "SignalAction.hxx"
  55. #include "VLog.hxx"
  56. using Vocal::Signals::SignalHandler;
  57. using Vocal::Signals::SignalAction;
  58. using Vocal::Signals::SignalSet;
  59. using Vocal::Logging::VLog;
  60. extern "C"
  61. {
  62. static void          
  63. localSignalHandler(int x, siginfo_t * siginfo, void * y)
  64. {
  65.     SignalHandler::signalHandler(x, siginfo, y);    
  66. }
  67.     
  68. }
  69. SignalHandler::SignalActionRefCountMap SignalHandler::myActionRefCountMap;
  70. SignalHandler::ThreadSignalMap      SignalHandler::myThreadSignalMap;
  71. void
  72. SignalHandler::init()
  73. {
  74.     const string    fn("SignalHandler::init");
  75.     VLog         log(fn);
  76.     
  77.     VVERBOSE(log) << fn << VVERBOSE_END(log);
  78. }
  79. void
  80. SignalHandler::uninit()
  81. {
  82.     const string    fn("SignalHandler::uninit");
  83.     VLog         log(fn);
  84.     
  85.     VVERBOSE(log) << fn << VVERBOSE_END(log);
  86.     for (   ThreadSignalMap::iterator it = myThreadSignalMap.begin();
  87.          it != myThreadSignalMap.end();
  88.     ++it
  89. )
  90.     {
  91.      delete it->second;
  92. it->second = 0;
  93.     }
  94.     
  95.     myThreadSignalMap.clear();
  96. }
  97. SignalHandler::SignalHandler()
  98. {
  99.     const string    fn("SignalHandler::SignalHandler");
  100.     VLog         log(fn);
  101.     
  102.     VVERBOSE(log) << fn << VVERBOSE_END(log);
  103.     ThreadSignalMap::iterator   i = myThreadSignalMap.find(VThread::selfId());
  104.     if ( i == myThreadSignalMap.end() )
  105.     {
  106.      myThreadSignalMap[VThread::selfId()] = new SignalActionMap;
  107.     }
  108.     else
  109.     {
  110.      // Can only have, at most, one signal handler per thread.
  111. //
  112.      assert( 0 );
  113.     }
  114. }
  115. SignalHandler::~SignalHandler()
  116. {
  117.     const string    fn("SignalHandler::~SignalHandler");
  118.     VLog         log(fn);
  119.     
  120.     VVERBOSE(log) << fn << VVERBOSE_END(log);
  121.     ThreadSignalMap::iterator   i = myThreadSignalMap.find(VThread::selfId());
  122.     if ( i != myThreadSignalMap.end() )
  123.     {
  124.         delete i->second;
  125.         myThreadSignalMap.erase(VThread::selfId());
  126.     }
  127. }
  128. void               
  129. SignalHandler::add(SignalAction & action)
  130. {
  131.     const string    fn("SignalHandler::add");
  132.     VLog         log(fn);
  133.     
  134.     // Find the signal map for this thread. It should exist since it
  135.     // is created during construction.
  136.     //
  137.     SignalActionMap * sam = myThreadSignalMap[VThread::selfId()];
  138.     assert( sam != 0 );
  139.     
  140.     SignalActionMap & signalActionMap = *sam;
  141.     VDEBUG(log) << fn << ": action = " << action << VDEBUG_END(log);
  142.     // For each signal, add it to the signal map
  143.     //
  144.     const vector<int> &   signals = action.signalSet().signalNumbers();
  145.     
  146.     size_t size = signals.size();
  147.     
  148.     for ( size_t i = 0; i < size; ++i )
  149.     {
  150.      int signum = signals[i];
  151.      signalActionMap[signum] = &action;
  152. // Set the sigaction to the static localSignalHandler(). Note that 
  153.         // there is one sigaction per signal number for the process. Thus the 
  154. // sigaction may have already been installed for these signal numbers.
  155. // However they should have been installed to use localSignalHandler(),
  156. // so reinstalling them doesn't hurt. 
  157. //
  158. SignalSet   blocked;
  159. blocked.fill();
  160. struct sigaction     sig_action;
  161. sig_action.sa_handler  = SIG_DFL;
  162. sig_action.sa_sigaction = localSignalHandler;
  163. sig_action.sa_mask   = blocked.signals;
  164. sig_action.sa_flags  = SA_SIGINFO;
  165. int rc = sigaction(signum, &sig_action, 0);
  166. assert ( rc == 0 );
  167.      // Increment the action reference count only AFTER the sigaction
  168. // has been set. If this hasn't been added to the map, the lookup 
  169. // will return 0, and the set will add it to the map.
  170. //
  171. myActionRefCountMap[signum] += 1;
  172.      VDEBUG(log) << fn << ": signum = " << signum 
  173.          << ", reference count = " << myActionRefCountMap[signum]
  174.     << VDEBUG_END(log);
  175.     }
  176. }
  177. void               
  178. SignalHandler::remove(SignalAction & action)
  179. {
  180.     const string    fn("SignalHandler::remove");
  181.     VLog         log(fn);
  182.     
  183.     // Find the signal map for this thread. It should exist since it
  184.     // is created during construction.
  185.     //
  186.     SignalActionMap * sam = myThreadSignalMap[VThread::selfId()];
  187.     assert( sam != 0 );
  188.     
  189.     SignalActionMap & signalActionMap = *sam;
  190.     VDEBUG(log) << fn << ": action = " << action << VDEBUG_END(log);
  191.     // For each signal, remove it from the signal map.
  192.     //
  193.     const vector<int> &   signals = action.signalSet().signalNumbers();
  194.     
  195.     size_t size = signals.size();
  196.     
  197.     for ( size_t i = 0; i < size; ++i )
  198.     {
  199.      int signum = signals[i];
  200.      // If this isn't the last reference, just decrement the counter.
  201.         //
  202.         SignalActionRefCountMap::iterator i = myActionRefCountMap.find(signum);
  203. size_t refCount = ( i == myActionRefCountMap.end() ? 0 : i->second );
  204. if ( refCount != 1 )
  205. {
  206.             if ( refCount > 1 )
  207.             {
  208.         myActionRefCountMap[signum] = --refCount;
  209.             }
  210.             else
  211.             {
  212.                 VWARN(log) << fn << ": trying to remove signal = " << signum 
  213.                            << ", but it hasn't been added to SignalHandler." 
  214.                            << VWARN_END(log);
  215.             }
  216.     continue;
  217. }
  218. // This is the last reference, so reset the sigaction to SIG_DFL
  219. // and take the signal out of the reference count map. Reset the
  220. // sigaction first to avoid races caused by inconsistent maps.
  221. //
  222.      // No blocked signals. Default constructs to empty.
  223. //
  224. SignalSet   noBlocked; 
  225. struct sigaction     sig_action;
  226. sig_action.sa_handler  = SIG_DFL;
  227. sig_action.sa_sigaction = 0;
  228. sig_action.sa_mask   = noBlocked.signals;
  229. sig_action.sa_flags  = 0;
  230. int rc = sigaction(signum, &sig_action, 0);
  231. assert ( rc == 0 );
  232.      myActionRefCountMap.erase(signum);
  233.      VDEBUG(log) << fn << ": signum = " << signum 
  234.          << ", removing action and using default."
  235.     << VDEBUG_END(log);
  236.      // Remove the action from the map AFTER the sigaction has been
  237. // reset. This avoids the race of a signal firing.
  238. //
  239.      signalActionMap.erase(signum);
  240.     }
  241. }
  242. void               
  243. SignalHandler::setBlocked(const SignalSet & signalSet)
  244. {
  245.     const string    fn("SignalHandler::setBlocked");
  246.     VLog         log(fn);
  247.     VDEBUG(log) << fn << ": signalSet = { " << signalSet << " }"
  248. << VDEBUG_END(log);
  249.     int rc = pthread_sigmask(SIG_SETMASK, &signalSet.signals, 0);
  250.     assert( rc == 0 );
  251. }
  252. void               
  253. SignalHandler::block(const SignalSet & signalSet)
  254. {
  255.     const string    fn("SignalHandler::block");
  256.     VLog         log(fn);
  257.     VDEBUG(log) << fn << ": signalSet = { " << signalSet << " }"
  258. << VDEBUG_END(log);
  259.     int rc = pthread_sigmask(SIG_BLOCK, &signalSet.signals, 0);
  260.     assert( rc == 0 );
  261. }
  262. void               
  263. SignalHandler::unblock(const SignalSet & signalSet)
  264. {
  265.     const string    fn("SignalHandler::unblock");
  266.     VLog         log(fn);
  267.     VDEBUG(log) << fn << ": signalSet = { " << signalSet << " }"
  268. << VDEBUG_END(log);
  269.     int rc = pthread_sigmask(SIG_UNBLOCK, &signalSet.signals, 0);
  270.     assert( rc == 0 );
  271. }
  272. void               
  273. SignalHandler::setGlobalBlocked(const SignalSet & signalSet)
  274. {
  275.     const string    fn("SignalHandler::setGlobalBlocked");
  276.     VLog         log(fn);
  277.     VDEBUG(log) << fn << ": signalSet = { " << signalSet << " }"
  278. << VDEBUG_END(log);
  279.     int rc = sigprocmask(SIG_SETMASK, &signalSet.signals, 0);
  280.     assert( rc == 0 );
  281. }
  282. void               
  283. SignalHandler::globalBlock(const SignalSet & signalSet)
  284. {
  285.     const string    fn("SignalHandler::globalBlock");
  286.     VLog         log(fn);
  287.     VDEBUG(log) << fn << ": signalSet = { " << signalSet << " }"
  288. << VDEBUG_END(log);
  289.     int rc = sigprocmask(SIG_BLOCK, &signalSet.signals, 0);
  290.     assert( rc == 0 );
  291. }
  292. void               
  293. SignalHandler::globalUnblock(const SignalSet & signalSet)
  294. {
  295.     const string    fn("SignalHandler::globalUnblock");
  296.     VLog         log(fn);
  297.     VDEBUG(log) << fn << ": signalSet = { " << signalSet << " }"
  298. << VDEBUG_END(log);
  299.     
  300.     int rc = sigprocmask(SIG_UNBLOCK, &signalSet.signals, 0);
  301.     assert( rc == 0 );
  302. }
  303. void          
  304. SignalHandler::signalHandler(int, siginfo_t * siginfo, void *)
  305. {
  306.     assert( siginfo != 0 );
  307.     ThreadSignalMap::iterator   i = myThreadSignalMap.find(VThread::selfId());
  308.     if ( i == myThreadSignalMap.end() )
  309.     {
  310.         assert( 0 );
  311.         return;
  312.     }
  313.         
  314.     SignalActionMap & signalActionMap = *(i->second);
  315.     int signum = siginfo->si_signo;
  316.     SignalActionMap::iterator j = signalActionMap.find(signum);
  317.     
  318.     if ( j == signalActionMap.end() )
  319.     {
  320.         assert( 0 );
  321.         return;
  322.     }
  323.     
  324.     SignalAction    * action = j->second;
  325.     
  326.     // Do the callback.
  327.     //
  328.     if ( action != 0 )
  329.     {
  330.      action->onSignal(signum, siginfo->si_errno, siginfo->si_code);
  331.     }
  332.     
  333.     // We shouldn't get here since we are reference counting the actions. 
  334.     //
  335.     else
  336.     {
  337.      assert( 0 );
  338.     }
  339. }