mirror of
https://github.com/debauchee/barrier.git
synced 2026-05-09 16:02:46 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user