258 lines
9.0 KiB
C++
Executable File
258 lines
9.0 KiB
C++
Executable File
#include <SignalManager.h>
|
|
|
|
#ifdef __linux
|
|
|
|
#ifndef SIGSYS
|
|
#define SIGSYS SIGUNUSED
|
|
#endif
|
|
|
|
#endif
|
|
|
|
// *****************************************************************************
|
|
// * SignalManager::reporter :
|
|
// * This is the declaration for the error reporter.
|
|
// *****************************************************************************
|
|
ErrorReporter SignalManager::reporter;
|
|
|
|
// *****************************************************************************
|
|
// * SignalHandler::SignalHandler :
|
|
// * This is the initializer for a SignalHandler class. It holds the
|
|
// * information needed to handle a single signal number.
|
|
// *****************************************************************************
|
|
_SignalHandler_::_SignalHandler_ ( void )
|
|
: signo(0), handler(NULL), oldHandler(NULL)
|
|
{
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalHandler::~SignalHandler :
|
|
// * This is the destructor for the SignlaHandler class. It will call the
|
|
// * uninstall method to remove the handler that was imposed for the signal.
|
|
// *****************************************************************************
|
|
_SignalHandler_::~_SignalHandler_ ( void )
|
|
{
|
|
uninstall ();
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalHandler::install :
|
|
// * This method will install the specified signal handler function on the
|
|
// * signal number specified by signo. The old handler will be preserved
|
|
// * for later restoration.
|
|
// *****************************************************************************
|
|
void _SignalHandler_::install ( int newSigno, SignalHandlerFunc newHandler )
|
|
{
|
|
// *********************************************************************
|
|
// * If a local signal handler has already been installed on the
|
|
// * specified signal number, uninstall it before proceeding.
|
|
// *********************************************************************
|
|
if(handler!=NULL && signo==newSigno) uninstall();
|
|
|
|
// *********************************************************************
|
|
// * Setup the control variables.
|
|
// *********************************************************************
|
|
signo = newSigno;
|
|
handler = newHandler;
|
|
|
|
// *********************************************************************
|
|
// * Install the new signal handler, preserving the old handler in the
|
|
// * oact sigaction structure.
|
|
// *********************************************************************
|
|
oldHandler = signal(signo, handler);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalHandler::uninstall :
|
|
// * This method will remove a user specified signal handler and will restore
|
|
// * the previously installed handler.
|
|
// *****************************************************************************
|
|
void _SignalHandler_::uninstall ( void )
|
|
{
|
|
// *********************************************************************
|
|
// * Check to see if the signal handler has been installed. If so,
|
|
// * call sigaction to confirm that the current signal handler is the
|
|
// * one that was installed.
|
|
// *********************************************************************
|
|
if(signo!=0 && handler!=NULL)
|
|
{
|
|
SignalHandlerFunc current = signal(signo, SIG_DFL);
|
|
if(current==handler) signal(signo, oldHandler);
|
|
else signal(signo, current);
|
|
}
|
|
|
|
signo = 0;
|
|
handler = NULL;
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalManager::installHandler :
|
|
// * This method will install the specified signal handler.
|
|
// *****************************************************************************
|
|
void SignalManager::installHandler (int signo, SignalHandlerFunc handler )
|
|
{
|
|
if(signo>0 && signo<=MAXSIGNAL) signals[signo-1].install(signo, handler);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalManager::uninstallHandler :
|
|
// * This method will remove a signal handler that was previously installed.
|
|
// *****************************************************************************
|
|
void SignalManager::uninstallHandler ( int signo )
|
|
{
|
|
if(signo>0 && signo<=MAXSIGNAL) signals[signo-1].uninstall();
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalManager::installDefaults :
|
|
// * This method will install a default collection of signal handlers.
|
|
// *****************************************************************************
|
|
void SignalManager::installDefaults ( void )
|
|
{
|
|
static int sigList[] =
|
|
{
|
|
#if !defined (_WIN32)
|
|
SIGFPE, // Erroneous arithmetic operation.
|
|
SIGHUP, // Hangup.
|
|
SIGILL, // Illegal instruction.
|
|
SIGINT, // Terminal interrupt signal.
|
|
SIGPIPE, // Write on a socket with no one to read
|
|
SIGQUIT, // Terminal quit signal.
|
|
SIGSEGV, // Invalid memory reference.
|
|
SIGTERM, // Termination signal.
|
|
SIGBUS, // Bus error.
|
|
SIGSYS, // Bad system call.
|
|
#else
|
|
SIGABRT, // Process abort signal.
|
|
SIGFPE, // Erroneous arithmetic operation.
|
|
SIGILL, // Illegal instruction.
|
|
SIGINT, // Terminal interrupt signal.
|
|
SIGSEGV, // Invalid memory reference.
|
|
SIGTERM, // Termination signal.
|
|
#endif
|
|
0
|
|
};
|
|
|
|
for(int i=0; sigList[i]!=0; i++) installHandler(sigList[i], defaultHandler);
|
|
}
|
|
|
|
// *****************************************************************************
|
|
// * SignalManager::defaultHandler :
|
|
// * This is the default signal handler method.
|
|
// *****************************************************************************
|
|
void SignalManager::defaultHandler( int signo )
|
|
{
|
|
switch(signo)
|
|
{
|
|
// *************************************************************
|
|
// * Process the interrupt signal by reporting it and exiting.
|
|
// *************************************************************
|
|
case SIGINT:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_INFO,
|
|
"Signal Manager",
|
|
"[SIGINT] Terminating at user's request");
|
|
exit(0);
|
|
|
|
// *************************************************************
|
|
// * Process the terminate signal by reporting it and exiting.
|
|
// *************************************************************
|
|
case SIGTERM:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_INFO,
|
|
"Signal Manager",
|
|
"[SIGTERM] Terminating normally");
|
|
exit(0);
|
|
|
|
// *************************************************************
|
|
// * Process abort signal by reporting the error and exiting.
|
|
// *************************************************************
|
|
case SIGABRT:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_SEVERE,
|
|
"Signal Manager",
|
|
"[SIGABRT] Application terminating due to abort signal");
|
|
abort();
|
|
|
|
|
|
// *************************************************************
|
|
// * Process erroneous arithmetic operations by reporting them
|
|
// * and exiting.
|
|
// *************************************************************
|
|
case SIGFPE:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_SEVERE,
|
|
"Signal Manager",
|
|
"[SIGFPE] Floating point error - terminating\n");
|
|
abort();
|
|
|
|
|
|
// *************************************************************
|
|
// * Process illegal instructions by reporting them and exiting.
|
|
// *************************************************************
|
|
case SIGILL:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_SEVERE,
|
|
"Signal Manager",
|
|
"[SIGILL] Illegal instruction");
|
|
abort();
|
|
|
|
// *************************************************************
|
|
// * Process the segmentation fault signal by reporting the
|
|
// * error and terminating.
|
|
// *************************************************************
|
|
case SIGSEGV:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_SEVERE,
|
|
"Signal Manager",
|
|
"[SIGSEGV] Segmentation fault");
|
|
abort();
|
|
|
|
#if !defined(_WIN32)
|
|
// *************************************************************
|
|
// * Report pipe errors, however, do not terminate.
|
|
// *************************************************************
|
|
case SIGPIPE:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_ERROR,
|
|
"Signal Manager",
|
|
"[SIGPIPE] Write on a pipe with no one to read it");
|
|
errno = SIGPIPE;
|
|
break;
|
|
|
|
// *************************************************************
|
|
// * Process a bus error by reporting it and exiting.
|
|
// *************************************************************
|
|
case SIGBUS:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_SEVERE,
|
|
"Signal Manager",
|
|
"[SIGBUS] Bus error");
|
|
abort();
|
|
|
|
// *************************************************************
|
|
// * Process a bad system call by reporting it and exiting.
|
|
// *************************************************************
|
|
case SIGSYS:
|
|
reporter.outputError (
|
|
CDEV_SEVERITY_SEVERE,
|
|
"Signal Manager",
|
|
"[SIGSYS] Bad system call");
|
|
abort();
|
|
|
|
// *************************************************************
|
|
// * Ignore the following signals:
|
|
// * SIGHUP: hangup signal.
|
|
// * SIGQUIT: terminal quit signal
|
|
// * default: All other signals
|
|
// *************************************************************
|
|
case SIGHUP:
|
|
case SIGQUIT:
|
|
#endif
|
|
|
|
default:
|
|
break;
|
|
}
|
|
signal(signo, SignalManager::defaultHandler);
|
|
}
|
|
|