signal.cpp

00001 
00002 /***************************************************************************
00003  *  signal.cpp - This header defines a trule OOo signal handler
00004  *  based on
00005  *  Douglas C. Schmidt
00006  *  "Applying Design Patterns to Simplify Signal Handling"
00007  *  http://www.cs.wustl.edu/~schmidt/signal-patterns.html
00008  *
00009  *  Generated: Thu Jan 12 22:55:34 2006
00010  *  Copyright  2005-2006  Tim Niemueller [www.niemueller.de]
00011  *
00012  ****************************************************************************/
00013 
00014 /*  This program is free software; you can redistribute it and/or modify
00015  *  it under the terms of the GNU General Public License as published by
00016  *  the Free Software Foundation; either version 2 of the License, or
00017  *  (at your option) any later version. A runtime exception applies to
00018  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00019  *
00020  *  This program is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU Library General Public License for more details.
00024  *
00025  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00026  */
00027 
00028 #include <utils/system/signal.h>
00029 #include <cstdlib>
00030 
00031 namespace fawkes {
00032 
00033 /** @class SignalHandler utils/system/signal.h
00034  * Interface for signal handling.
00035  * Derive this class and implement handle_signal() to handle signals.
00036  * The handler must then be registered via SignalManager::register_handler().
00037  * From then on handle_signal() is called if the desired signal has been received.
00038  *
00039  * @fn SignalHandler::~SignalHandler()
00040  * Virtual destructor.
00041  *
00042  * @fn void SignalHandler::handle_signal(int signum)
00043  * Signal hanlding method.
00044  * Implement this method with the action you want to perform on the registered
00045  * signals.
00046  * @param signum signal number of triggered signal
00047  *
00048  * @author Tim Niemueller
00049  */
00050 
00051 /** @class SignalManager utils/system/signal.h
00052  * System signal manager.
00053  * This class dispatches signals received from the system to the appropriate
00054  * handlers or sets a signal to be ignored.
00055  * This class is never instantiated but rather you just register a handler.
00056  * After you are done with signal handling call finalize() to free the
00057  * use resources and de-register all signal handlers at once.
00058  *
00059  * @author Tim Niemueller
00060  */
00061 
00062 SignalManager *  SignalManager::__instance = NULL;
00063 SignalHandler *  SignalManager::__signal_handlers[NSIG];
00064 
00065 /** Invalid constructor. */
00066 SignalManager::SignalManager()
00067 {
00068 }
00069 
00070 
00071 /** Invalid copy constructor. */
00072 SignalManager::SignalManager(const SignalManager &cc)
00073 {
00074 }
00075 
00076 
00077 /** Get the SignalManager instance
00078  * @return SignalManager instance
00079  */
00080 SignalManager *
00081 SignalManager::instance()
00082 {
00083   if ( __instance == NULL ) {
00084     __instance = new SignalManager();
00085     for (unsigned int i = 0; i < NSIG; ++i) {
00086       __signal_handlers[i] = NULL;
00087     }
00088   }
00089 
00090   return __instance;
00091 }
00092 
00093 
00094 /** Finalize (and free) the SignalManager instance, this does NOT
00095  * implicitly delete the signal handlers, you have to do this by yourself
00096  */
00097 void
00098 SignalManager::finalize()
00099 {
00100   if ( __instance != NULL ) {
00101     for (unsigned int i = 0; i < NSIG; ++i) {
00102       restore_default(i);
00103     }
00104     delete __instance;
00105     __instance = NULL;
00106   }
00107 }
00108 
00109 
00110 /** Register a SignalHandler for a signal
00111  * @param signum The signal number from <signal.h>
00112  * @param handler The SignalHandler that should handle this event
00113  * @return The SignalManager registered before, maybe NULL if there was none
00114  */
00115 SignalHandler *
00116 SignalManager::register_handler(int signum, SignalHandler *handler)
00117 {
00118   if (signum < NSIG) {
00119     SignalHandler *old = __signal_handlers[signum];
00120     __signal_handlers[signum] = handler;
00121 
00122     // Register the <dispatcher> to handle this <signum>.
00123     struct sigaction sa;
00124     sa.sa_handler = SignalManager::dispatcher;
00125     sigemptyset (&sa.sa_mask);
00126     sa.sa_flags = 0;
00127     sigaction (signum, &sa, 0);
00128 
00129     return old;
00130   } else {
00131     return NULL;
00132   }
00133 }
00134 
00135 
00136 /** Unregister a SignalHandler for a signal
00137  * @param signum The signal number from <signal.h>
00138  */
00139 void
00140 SignalManager::unregister_handler(int signum)
00141 {
00142   restore_default(signum);
00143 }
00144 
00145 
00146 /** Unregister a SignalHandler for a signal
00147  * @param handler The SignalHandler you want to unregister, will unregister
00148  *                all signals this handler was registered for
00149  */
00150 void
00151 SignalManager::unregister_handler(SignalHandler *handler)
00152 {
00153 
00154   for (unsigned int i = 0; i < NSIG; ++i) {
00155     if ( __signal_handlers[i] == handler ) {
00156       restore_default(i);
00157     }
00158   }
00159 }
00160 
00161 
00162 void
00163 SignalManager::restore_default(int signum)
00164 {
00165   if (signum < NSIG) {
00166     __signal_handlers[signum] = NULL;
00167 
00168     // ignore this signal
00169     struct sigaction sa;
00170     sa.sa_handler = SIG_DFL;
00171     sigemptyset (&sa.sa_mask);
00172     sa.sa_flags = 0;
00173     sigaction (signum, &sa, 0);
00174   }
00175 }
00176 
00177 
00178 /** Ignore a signal
00179  * @param signum The signal number from <signal.h>
00180  */
00181 void
00182 SignalManager::ignore(int signum)
00183 {
00184   if (signum < NSIG) {
00185     __signal_handlers[signum] = NULL;
00186 
00187     // ignore this signal
00188     struct sigaction sa;
00189     sa.sa_handler = SIG_IGN;
00190     sigemptyset (&sa.sa_mask);
00191     sa.sa_flags = 0;
00192     sigaction (signum, &sa, 0);
00193   }
00194 }
00195 
00196 
00197 /** Dispatch incoming signal to appropriate handler.
00198  * @param signum signal received.
00199  */
00200 void
00201 SignalManager::dispatcher(int signum)
00202 {
00203   if (__signal_handlers[signum] != NULL) {
00204     __signal_handlers[signum]->handle_signal(signum);
00205   }
00206 }
00207 
00208 } // end namespace fawkes

Generated on Tue Feb 22 13:31:28 2011 for Fawkes API by  doxygen 1.4.7