Fawkes API Fawkes Development Version
|
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