libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 // (c) COPYRIGHT URI/MIT 1994-2002 00027 // Please read the full copyright statement in the file COPYRIGHT_URI. 00028 // 00029 // Authors: 00030 // jhrg,jimg James Gallagher <jgallagher@gso.uri.edu> 00031 00032 #include "config.h" 00033 00034 static char rcsid[] not_used = 00035 { "$Id: SignalHandler.cc 18500 2008-03-19 19:39:45Z jimg $" 00036 }; 00037 00038 #include <signal.h> 00039 #include <pthread.h> 00040 00041 #ifdef HAVE_UNISTD_H 00042 #include <unistd.h> //for _exit 00043 #endif 00044 00045 #include "SignalHandler.h" 00046 #include "util.h" 00047 00048 namespace libdap { 00049 00050 EventHandler *SignalHandler::d_signal_handlers[NSIG]; 00051 Sigfunc *SignalHandler::d_old_handlers[NSIG]; 00052 SignalHandler *SignalHandler::d_instance = 0; 00053 00054 // instance_control is used to ensure that in a MT environment d_instance is 00055 // correctly initialized. 00056 static pthread_once_t instance_control = PTHREAD_ONCE_INIT; 00057 00059 void 00060 SignalHandler::initialize_instance() 00061 { 00062 // MT-Safe if called via pthread_once or similar 00063 SignalHandler::d_instance = new SignalHandler; 00064 atexit(SignalHandler::delete_instance); 00065 } 00066 00068 void 00069 SignalHandler::delete_instance() 00070 { 00071 if (SignalHandler::d_instance) { 00072 for (int i = 0; i < NSIG; ++i) { 00073 // Fortify warns about a leak because the EventHandler objects 00074 // are not deleted, but that's OK - this is a singleton and 00075 // so the 'leak' is really just a constant amount of memory that 00076 // gets used. 00077 d_signal_handlers[i] = 0; 00078 d_old_handlers[i] = 0; 00079 } 00080 00081 delete SignalHandler::d_instance; 00082 SignalHandler::d_instance = 0; 00083 } 00084 } 00085 00092 void 00093 SignalHandler::dispatcher(int signum) 00094 { 00095 // Perform a sanity check... 00096 if (SignalHandler::d_signal_handlers[signum] != 0) 00097 // Dispatch the handler's hook method. 00098 SignalHandler::d_signal_handlers[signum]->handle_signal(signum); 00099 00100 Sigfunc *old_handler = SignalHandler::d_old_handlers[signum]; 00101 if (old_handler == SIG_IGN || old_handler == SIG_ERR) 00102 return; 00103 else if (old_handler == SIG_DFL) { 00104 switch (signum) { 00105 #ifndef WIN32 00106 case SIGHUP: 00107 case SIGKILL: 00108 case SIGUSR1: 00109 case SIGUSR2: 00110 case SIGPIPE: 00111 case SIGALRM: 00112 #endif 00113 case SIGINT: 00114 case SIGTERM: _exit(EXIT_FAILURE); 00115 00116 // register_handler() should never allow any fiddling with 00117 // signals other than those listed above. 00118 default: abort(); 00119 } 00120 } 00121 else 00122 old_handler(signum); 00123 } 00124 00126 SignalHandler* 00127 SignalHandler::instance() 00128 { 00129 pthread_once(&instance_control, initialize_instance); 00130 00131 return d_instance; 00132 } 00133 00146 EventHandler * 00147 SignalHandler::register_handler(int signum, EventHandler *eh, bool override) 00148 { 00149 // Check first for improper use. 00150 switch (signum) { 00151 #ifndef WIN32 00152 case SIGHUP: 00153 case SIGKILL: 00154 case SIGUSR1: 00155 case SIGUSR2: 00156 case SIGPIPE: 00157 case SIGALRM: 00158 #endif 00159 case SIGINT: 00160 case SIGTERM: break; 00161 00162 default: throw InternalErr(__FILE__, __LINE__, 00163 string("Call to register_handler with unsupported signal (") 00164 + long_to_string(signum) + string(").")); 00165 } 00166 00167 // Save the old EventHandler 00168 EventHandler *old_eh = SignalHandler::d_signal_handlers[signum]; 00169 00170 SignalHandler::d_signal_handlers[signum] = eh; 00171 00172 // Register the dispatcher to handle this signal. See Stevens, Advanced 00173 // Programming in the UNIX Environment, p.298. 00174 #ifndef WIN32 00175 struct sigaction sa; 00176 sa.sa_handler = dispatcher; 00177 sigemptyset(&sa.sa_mask); 00178 sa.sa_flags = 0; 00179 00180 // Try to suppress restarting system calls if we're handling an alarm. 00181 // This lets alarms block I/O calls that would normally restart. 07/18/03 00182 // jhrg 00183 if (signum == SIGALRM) { 00184 #ifdef SA_INTERUPT 00185 sa.sa_flags |= SA_INTERUPT; 00186 #endif 00187 } 00188 else { 00189 #ifdef SA_RESTART 00190 sa.sa_flags |= SA_RESTART; 00191 #endif 00192 } 00193 00194 struct sigaction osa; // extract the old handler/action 00195 00196 if (sigaction(signum, &sa, &osa) < 0) 00197 throw InternalErr(__FILE__, __LINE__, "Could not register a signal handler."); 00198 00199 // Take care of the case where this interface is used to register a 00200 // handler more than once. We want to make sure that the dispatcher is 00201 // not installed as the 'old handler' because that results in an infinite 00202 // loop. 02/10/04 jhrg 00203 if (override) 00204 SignalHandler::d_old_handlers[signum] = SIG_IGN; 00205 else if (osa.sa_handler != dispatcher) 00206 SignalHandler::d_old_handlers[signum] = osa.sa_handler; 00207 #endif 00208 00209 return old_eh; 00210 } 00211 00215 EventHandler * 00216 SignalHandler::remove_handler(int signum) 00217 { 00218 EventHandler *old_eh = SignalHandler::d_signal_handlers[signum]; 00219 00220 SignalHandler::d_signal_handlers[signum] = 0; 00221 00222 return old_eh; 00223 } 00224 00225 } // namespace libdap