added SIGINT and SIGTERM handling to unix client and server.

either signal causes the main thread to be cancelled.  added
necessary code to make main thread cancellation clean up
nicely.
This commit is contained in:
crs 2002-06-02 18:49:35 +00:00
parent 1da9be88c9
commit 1d3807cb0e
7 changed files with 115 additions and 25 deletions

View File

@ -6,11 +6,12 @@
#include "ISecondaryScreen.h"
#include "ProtocolTypes.h"
#include "CLock.h"
#include "CLog.h"
#include "CThread.h"
#include "CTimerThread.h"
#include "XSynergy.h"
#include "TMethodJob.h"
#include "CLog.h"
#include "XSynergy.h"
#include "XThread.h"
#include <assert.h>
#include <memory>
@ -71,6 +72,7 @@ void CClient::run(const CNetworkAddress& serverAddress)
log((CLOG_ERR "client error: %s", e.what()));
// clean up
log((CLOG_NOTE "stopping client"));
if (thread != NULL) {
thread->cancel();
thread->wait();
@ -78,10 +80,22 @@ void CClient::run(const CNetworkAddress& serverAddress)
}
closeSecondaryScreen();
}
catch (XThread&) {
// clean up
log((CLOG_NOTE "stopping client"));
if (thread != NULL) {
thread->cancel();
thread->wait();
delete thread;
}
closeSecondaryScreen();
throw;
}
catch (...) {
log((CLOG_DEBUG "unknown client error"));
// clean up
log((CLOG_NOTE "stopping client"));
if (thread != NULL) {
thread->cancel();
thread->wait();

View File

@ -5,6 +5,7 @@
#include "CNetwork.h"
#include "CNetworkAddress.h"
#include "CThread.h"
#include "XThread.h"
#include <assert.h>
//
@ -42,20 +43,24 @@ void realMain(const CString& name,
s_logMutex = &logMutex;
CLog::setLock(&logLock);
CClient* client = NULL;
try {
// initialize network library
CNetwork::init();
CClient* client = NULL;
try {
// run client
CNetworkAddress addr(hostname, port);
client = new CClient(name);
client->run(addr);
// clean up
delete client;
CNetwork::cleanup();
CLog::setLock(NULL);
s_logMutex = NULL;
}
catch (...) {
// clean up
delete client;
CNetwork::cleanup();
CLog::setLock(NULL);
@ -93,6 +98,10 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
MessageBox(NULL, msg.c_str(), "error", MB_OK | MB_ICONERROR);
return 1;
}
catch (XThread&) {
// terminated
return 1;
}
}
#else
@ -114,6 +123,10 @@ int main(int argc, char** argv)
fprintf(stderr, "failed: %s\n", e.what());
return 1;
}
catch (XThread&) {
// terminated
return 1;
}
}
#endif

View File

@ -1,7 +1,7 @@
#ifndef CTHREAD_H
#define CTHREAD_H
#include "common.h"
#include "BasicTypes.h"
class IJob;
class CThreadRep;

View File

@ -40,6 +40,9 @@ static void threadDebug(int)
CMutex* CThreadRep::s_mutex = NULL;
CThreadRep* CThreadRep::s_head = NULL;
#if defined(CONFIG_PTHREADS)
pthread_t CThreadRep::s_signalThread;
#endif
CThreadRep::CThreadRep() : m_prev(NULL),
m_next(NULL),
@ -92,7 +95,14 @@ CThreadRep::CThreadRep(IJob* job, void* userData) :
// start the thread. throw if it doesn't start.
#if defined(CONFIG_PTHREADS)
// 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);
int status = pthread_create(&m_thread, NULL, threadFunc, (void*)this);
pthread_sigmask(SIG_SETMASK, &oldsigset, NULL);
if (status != 0)
throw XThreadUnavailable();
#elif defined(CONFIG_PLATFORM_WIN32)
@ -164,7 +174,22 @@ void CThreadRep::initThreads()
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
sigemptyset(&sigset);
sigaddset(&sigset, SIGPIPE);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
// fire up the INT and TERM signal handler thread
int status = pthread_create(&s_signalThread, NULL,
&CThreadRep::threadSignalHandler,
getCurrentThreadRep());
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);
}
#endif
}
}
@ -338,8 +363,9 @@ void CThreadRep::cancel()
void CThreadRep::testCancel()
{
{
// prevent further cancellation
CLock lock(s_mutex);
// done if not cancelled, not cancellable, or already cancelling
if (!m_cancel || !m_cancellable || m_cancelling)
return;
@ -393,18 +419,6 @@ void* CThreadRep::threadFunc(void* arg)
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
// set signal mask
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGWAKEUP);
#ifndef NDEBUG
sigaddset(&sigset, SIGSEGV);
#endif
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
sigemptyset(&sigset);
sigaddset(&sigset, SIGPIPE);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
// run thread
rep->doThreadFunc();
@ -426,6 +440,27 @@ void CThreadRep::threadCancel(int)
// do nothing
}
void* CThreadRep::threadSignalHandler(void* vrep)
{
CThreadRep* mainThreadRep = reinterpret_cast<CThreadRep*>(vrep);
// add signal to mask
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
// we exit the loop via thread cancellation in sigwait()
for (;;) {
// wait
int signal;
sigwait(&sigset, &signal);
// if we get here then the signal was raised. cancel the thread.
mainThreadRep->cancel();
}
}
#elif defined(CONFIG_PLATFORM_WIN32)
void CThreadRep::init()

View File

@ -85,6 +85,7 @@ private:
#if defined(CONFIG_PTHREADS)
static void* threadFunc(void* arg);
static void threadCancel(int);
static void* threadSignalHandler(void*);
#elif defined(CONFIG_PLATFORM_WIN32)
static unsigned int __stdcall threadFunc(void* arg);
#endif
@ -107,11 +108,13 @@ private:
void* m_result;
bool m_cancellable;
bool m_cancelling;
UInt32 m_signals;
#if defined(CONFIG_PTHREADS)
pthread_t m_thread;
bool m_exit;
bool m_cancel;
static pthread_t s_signalThread;
#endif
#if defined(CONFIG_PLATFORM_WIN32)

View File

@ -7,18 +7,19 @@
#include "IPrimaryScreen.h"
#include "ISocketFactory.h"
#include "ProtocolTypes.h"
#include "XSynergy.h"
#include "CNetworkAddress.h"
#include "ISocket.h"
#include "IListenSocket.h"
#include "XSocket.h"
#include "CLock.h"
#include "CLog.h"
#include "CThread.h"
#include "CTimerThread.h"
#include "CStopwatch.h"
#include "CFunctionJob.h"
#include "TMethodJob.h"
#include "CLog.h"
#include "XSocket.h"
#include "XSynergy.h"
#include "XThread.h"
#include <assert.h>
#include <memory>
@ -92,15 +93,26 @@ void CServer::run()
log((CLOG_ERR "server error: %s", e.what()));
// clean up
log((CLOG_NOTE "stopping server"));
delete m_httpServer;
m_httpServer = NULL;
cleanupThreads();
closePrimaryScreen();
}
catch (XThread&) {
// clean up
log((CLOG_NOTE "stopping server"));
delete m_httpServer;
m_httpServer = NULL;
cleanupThreads();
closePrimaryScreen();
throw;
}
catch (...) {
log((CLOG_DEBUG "unknown server error"));
// clean up
log((CLOG_NOTE "stopping server"));
delete m_httpServer;
m_httpServer = NULL;
cleanupThreads();

View File

@ -4,6 +4,7 @@
#include "CMutex.h"
#include "CNetwork.h"
#include "CThread.h"
#include "XThread.h"
#include "stdfstream.h"
#include <assert.h>
@ -47,11 +48,12 @@ void realMain()
s_logMutex = &logMutex;
CLog::setLock(&logLock);
CServer* server = NULL;
try {
// initialize network library
CNetwork::init();
CServer* server = NULL;
try {
// load configuration
CConfig config;
{
log((CLOG_DEBUG "opening configuration"));
@ -63,9 +65,12 @@ void realMain()
log((CLOG_DEBUG "configuration read successfully"));
}
// run server
server = new CServer();
server->setConfig(config);
server->run();
// clean up
delete server;
CNetwork::cleanup();
CLog::setLock(NULL);
@ -110,6 +115,10 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
MessageBox(NULL, msg.c_str(), "error", MB_OK | MB_ICONERROR);
return 1;
}
catch (XThread&) {
// terminated
return 1;
}
}
#else
@ -132,6 +141,10 @@ int main(int argc, char** argv)
fprintf(stderr, "failed: %s\n", e.what());
return 1;
}
catch (XThread&) {
// terminated
return 1;
}
}
#endif