Generalized signal handling. Now handling SIGHUP in addition

to SIGINT and SIGTERM.  Setup SIGHUP to reload the server's
configuration.
This commit is contained in:
crs
2004-02-28 17:49:29 +00:00
parent 9f7e909361
commit 82dffeb498
11 changed files with 183 additions and 88 deletions

View File

@@ -376,15 +376,15 @@ CArch::getIDOfThread(CArchThread thread)
}
void
CArch::setInterruptHandler(InterruptFunc func, void* userData)
CArch::setSignalHandler(ESignal signal, SignalFunc func, void* userData)
{
m_mt->setInterruptHandler(func, userData);
m_mt->setSignalHandler(signal, func, userData);
}
void
CArch::interrupt()
CArch::raiseSignal(ESignal signal)
{
m_mt->interrupt();
m_mt->raiseSignal(signal);
}
CArchSocket

View File

@@ -120,8 +120,8 @@ public:
virtual bool isExitedThread(CArchThread);
virtual void* getResultOfThread(CArchThread);
virtual ThreadID getIDOfThread(CArchThread);
virtual void setInterruptHandler(InterruptFunc, void*);
virtual void interrupt();
virtual void setSignalHandler(ESignal, SignalFunc, void*);
virtual void raiseSignal(ESignal);
// IArchNetwork overrides
virtual CArchSocket newSocket(EAddressFamily, ESocketType);

View File

@@ -108,9 +108,20 @@ CArchConsoleWindows::getNewlineForConsole()
}
BOOL WINAPI
CArchConsoleWindows::signalHandler(DWORD)
CArchConsoleWindows::signalHandler(DWORD ctrlType)
{
// terminate app and skip remaining handlers
ARCH->interrupt();
return TRUE;
switch (ctrlType) {
case CTRL_C_EVENT:
ARCH->raiseSignal(CArch::kINTERRUPT);
return TRUE;
case CTRL_BREAK_EVENT:
ARCH->raiseSignal(CArch::kTERMINATE);
return TRUE;
default:
ARCH->raiseSignal(CArch::kINTERRUPT);
return TRUE;
}
}

View File

@@ -41,6 +41,16 @@
# define HAVE_POSIX_SIGWAIT 1
#endif
static
void
setSignalSet(sigset_t* sigset)
{
sigemptyset(sigset);
sigaddset(sigset, SIGHUP);
sigaddset(sigset, SIGINT);
sigaddset(sigset, SIGTERM);
}
//
// CArchThreadImpl
//
@@ -83,14 +93,18 @@ CArchMultithreadPosix* CArchMultithreadPosix::s_instance = NULL;
CArchMultithreadPosix::CArchMultithreadPosix() :
m_newThreadCalled(false),
m_nextID(0),
m_signalFunc(NULL),
m_signalUserData(NULL)
m_nextID(0)
{
assert(s_instance == NULL);
s_instance = this;
// no signal handlers
for (size_t i = 0; i < kNUM_SIGNALS; ++i) {
m_signalFunc[i] = NULL;
m_signalUserData[i] = NULL;
}
// create mutex for thread list
m_threadMutex = newMutex();
@@ -353,13 +367,6 @@ CArchMultithreadPosix::newThread(ThreadFunc func, void* data)
thread->m_func = func;
thread->m_userData = data;
// mask some signals in all threads except the main thread
sigset_t sigset, oldsigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
pthread_sigmask(SIG_BLOCK, &sigset, &oldsigset);
// create the thread. pthread_create() on RedHat 7.2 smp fails
// if passed a NULL attr so use a default attr.
pthread_attr_t attr;
@@ -370,9 +377,6 @@ CArchMultithreadPosix::newThread(ThreadFunc func, void* data)
pthread_attr_destroy(&attr);
}
// restore signals
pthread_sigmask(SIG_SETMASK, &oldsigset, NULL);
// check if thread was started
if (status != 0) {
// failed to start thread so clean up
@@ -560,23 +564,24 @@ CArchMultithreadPosix::getIDOfThread(CArchThread thread)
}
void
CArchMultithreadPosix::setInterruptHandler(InterruptFunc func, void* userData)
CArchMultithreadPosix::setSignalHandler(
ESignal signal, SignalFunc func, void* userData)
{
lockMutex(m_threadMutex);
m_signalFunc = func;
m_signalUserData = userData;
m_signalFunc[signal] = func;
m_signalUserData[signal] = userData;
unlockMutex(m_threadMutex);
}
void
CArchMultithreadPosix::interrupt()
CArchMultithreadPosix::raiseSignal(ESignal signal)
{
lockMutex(m_threadMutex);
if (m_signalFunc != NULL) {
m_signalFunc(m_signalUserData);
if (m_signalFunc[signal] != NULL) {
m_signalFunc[signal](signal, m_signalUserData[signal]);
unblockThread(m_mainThread);
}
else {
else if (signal == kINTERRUPT || signal == kTERMINATE) {
ARCH->cancelThread(m_mainThread);
}
unlockMutex(m_threadMutex);
@@ -587,11 +592,9 @@ CArchMultithreadPosix::startSignalHandler()
{
// set signal mask. the main thread blocks these signals and
// the signal handler thread will listen for them.
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
sigset_t sigset, oldsigset;
setSignalSet(&sigset);
pthread_sigmask(SIG_BLOCK, &sigset, &oldsigset);
// fire up the INT and TERM signal handler thread. we could
// instead arrange to catch and handle these signals but
@@ -608,10 +611,7 @@ CArchMultithreadPosix::startSignalHandler()
if (status != 0) {
// can't create thread to wait for signal so don't block
// the signals.
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
pthread_sigmask(SIG_UNBLOCK, &oldsigset, NULL);
}
}
@@ -766,9 +766,7 @@ CArchMultithreadPosix::threadSignalHandler(void*)
// add signal to mask
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
setSignalSet(&sigset);
// also wait on SIGABRT. on linux (others?) this thread (process)
// will persist after all the other threads evaporate due to an
@@ -791,6 +789,22 @@ CArchMultithreadPosix::threadSignalHandler(void*)
#endif
// if we get here then the signal was raised
ARCH->interrupt();
switch (signal) {
case SIGINT:
ARCH->raiseSignal(kINTERRUPT);
break;
case SIGTERM:
ARCH->raiseSignal(kTERMINATE);
break;
case SIGHUP:
ARCH->raiseSignal(kHANGUP);
break;
default:
// ignore
break;
}
}
}

View File

@@ -72,8 +72,8 @@ public:
virtual bool isExitedThread(CArchThread);
virtual void* getResultOfThread(CArchThread);
virtual ThreadID getIDOfThread(CArchThread);
virtual void setInterruptHandler(InterruptFunc, void*);
virtual void interrupt();
virtual void setSignalHandler(ESignal, SignalFunc, void*);
virtual void raiseSignal(ESignal);
private:
void startSignalHandler();
@@ -104,8 +104,8 @@ private:
ThreadID m_nextID;
pthread_t m_signalThread;
InterruptFunc m_signalFunc;
void* m_signalUserData;
SignalFunc m_signalFunc[kNUM_SIGNALS];
void* m_signalUserData[kNUM_SIGNALS];
};
#endif

View File

@@ -80,13 +80,17 @@ CArchThreadImpl::~CArchThreadImpl()
CArchMultithreadWindows* CArchMultithreadWindows::s_instance = NULL;
CArchMultithreadWindows::CArchMultithreadWindows() :
m_signalFunc(NULL),
m_signalUserData(NULL)
CArchMultithreadWindows::CArchMultithreadWindows()
{
assert(s_instance == NULL);
s_instance = this;
// no signal handlers
for (size_t i = 0; i < kNUM_SIGNALS; ++i) {
m_signalFunc[i] = NULL;
m_signalUserData[i] = NULL;
}
// create mutex for thread list
m_threadMutex = newMutex();
@@ -529,23 +533,24 @@ CArchMultithreadWindows::getIDOfThread(CArchThread thread)
}
void
CArchMultithreadWindows::setInterruptHandler(InterruptFunc func, void* userData)
CArchMultithreadWindows::setSignalHandler(
ESignal signal, SignalFunc func, void* userData)
{
lockMutex(m_threadMutex);
m_signalFunc = func;
m_signalUserData = userData;
m_signalFunc[signal] = func;
m_signalUserData[signal] = userData;
unlockMutex(m_threadMutex);
}
void
CArchMultithreadWindows::interrupt()
CArchMultithreadWindows::raiseSignal(ESignal signal)
{
lockMutex(m_threadMutex);
if (m_signalFunc != NULL) {
m_signalFunc(m_signalUserData);
if (m_signalFunc[signal] != NULL) {
m_signalFunc[signal](signal, m_signalUserData[signal]);
ARCH->unblockPollSocket(m_mainThread);
}
else {
else if (signal == kINTERRUPT || signal == kTERMINATE) {
ARCH->cancelThread(m_mainThread);
}
unlockMutex(m_threadMutex);

View File

@@ -81,8 +81,8 @@ public:
virtual bool isExitedThread(CArchThread);
virtual void* getResultOfThread(CArchThread);
virtual ThreadID getIDOfThread(CArchThread);
virtual void setInterruptHandler(InterruptFunc, void*);
virtual void interrupt();
virtual void setSignalHandler(ESignal, SignalFunc, void*);
virtual void raiseSignal(ESignal);
private:
CArchThreadImpl* find(DWORD id);
@@ -107,8 +107,8 @@ private:
CThreadList m_threadList;
CArchThread m_mainThread;
InterruptFunc m_signalFunc;
void* m_signalUserData;
SignalFunc m_signalFunc[kNUM_SIGNALS];
void* m_signalUserData[kNUM_SIGNALS];
};
#endif

View File

@@ -71,6 +71,19 @@ public:
typedef void* (*ThreadFunc)(void*);
//! Type of thread identifier
typedef unsigned int ThreadID;
//! Types of signals
/*!
Not all platforms support all signals. Unsupported signals are
ignored.
*/
enum ESignal {
kINTERRUPT, //!< Interrupt (e.g. Ctrl+C)
kTERMINATE, //!< Terminate (e.g. Ctrl+Break)
kHANGUP, //!< Hangup (SIGHUP)
kNUM_SIGNALS
};
//! Type of signal handler function
typedef void (*SignalFunc)(ESignal, void* userData);
//! @name manipulators
//@{
@@ -242,12 +255,16 @@ public:
Sets the function to call on receipt of an external interrupt.
By default and when \p func is NULL, the main thread is cancelled.
*/
typedef void (*InterruptFunc)(void*);
virtual void setInterruptHandler(InterruptFunc func,
virtual void setSignalHandler(ESignal, SignalFunc func,
void* userData) = 0;
//! Invoke the interrupt handler
virtual void interrupt() = 0;
//! Invoke the signal handler
/*!
Invokes the signal handler for \p signal, if any. If no handler
cancels the main thread for \c kINTERRUPT and \c kTERMINATE and
ignores the call otherwise.
*/
virtual void raiseSignal(ESignal signal) = 0;
//@}
};

View File

@@ -1,4 +1,4 @@
/*
;/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2004 Chris Schoeneman
*
@@ -22,7 +22,7 @@
// interrupt handler. this just adds a quit event to the queue.
static
void
interrupt(void*)
interrupt(CArch::ESignal, void*)
{
EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
}
@@ -37,14 +37,16 @@ CEventQueue::CEventQueue() :
{
setInstance(this);
m_mutex = ARCH->newMutex();
ARCH->setInterruptHandler(&interrupt, NULL);
ARCH->setSignalHandler(CArch::kINTERRUPT, &interrupt, NULL);
ARCH->setSignalHandler(CArch::kTERMINATE, &interrupt, NULL);
m_buffer = new CSimpleEventQueueBuffer;
}
CEventQueue::~CEventQueue()
{
delete m_buffer;
ARCH->setInterruptHandler(NULL, NULL);
ARCH->setSignalHandler(CArch::kINTERRUPT, NULL, NULL);
ARCH->setSignalHandler(CArch::kTERMINATE, NULL, NULL);
ARCH->closeMutex(m_mutex);
setInstance(NULL);
}