diff --git a/server/CServer.cpp b/server/CServer.cpp index d10606b1..89ff7150 100644 --- a/server/CServer.cpp +++ b/server/CServer.cpp @@ -29,6 +29,10 @@ const SInt32 CServer::s_httpMaxSimultaneousRequests = 3; CServer::CServer(const CString& serverName) : m_name(serverName), + m_bindTimeout(5.0 * 60.0), + m_socketFactory(NULL), + m_securityFactory(NULL), + m_acceptClientThread(NULL), m_active(NULL), m_primaryClient(NULL), m_seqNum(0), @@ -36,9 +40,7 @@ CServer::CServer(const CString& serverName) : m_httpServer(NULL), m_httpAvailable(&m_mutex, s_httpMaxSimultaneousRequests) { - m_socketFactory = NULL; - m_securityFactory = NULL; - m_bindTimeout = 5.0 * 60.0; + // do nothing } CServer::~CServer() @@ -82,7 +84,9 @@ CServer::run() log((CLOG_NOTE "starting server")); // start listening for new clients - startThread(new TMethodJob(this, &CServer::acceptClients)); + m_acceptClientThread = new CThread(startThread( + new TMethodJob(this, + &CServer::acceptClients))); // start listening for HTTP requests if (m_config.getHTTPAddress().isValid()) { @@ -220,6 +224,7 @@ CServer::onError() stopThreads(3.0); // done with the HTTP server + CLock lock(&m_mutex); delete m_httpServer; m_httpServer = NULL; @@ -1016,7 +1021,7 @@ CServer::closeClients(const CConfig& config) reapThreads(); } -void +CThread CServer::startThread(IJob* job) { CLock lock(&m_mutex); @@ -1025,8 +1030,10 @@ CServer::startThread(IJob* job) doReapThreads(m_threads); // add new thread to list. use the job as user data for logging. - m_threads.push_back(CThread(job, job)); - log((CLOG_DEBUG1 "started thread %p", m_threads.back().getUserData())); + CThread thread(job, job); + m_threads.push_back(thread); + log((CLOG_DEBUG1 "started thread %p", thread.getUserData())); + return thread; } void @@ -1034,6 +1041,20 @@ CServer::stopThreads(double timeout) { log((CLOG_DEBUG1 "stopping threads")); + // cancel the accept client thread to prevent more clients from + // connecting while we're shutting down. + CThread* acceptClientThread; + { + CLock lock(&m_mutex); + acceptClientThread = m_acceptClientThread; + m_acceptClientThread = NULL; + } + if (acceptClientThread != NULL) { + acceptClientThread->cancel(); + acceptClientThread->wait(timeout); + delete acceptClientThread; + } + // close all clients (except the primary) { CConfig emptyConfig; diff --git a/server/CServer.h b/server/CServer.h index 734d8906..0a34c9a6 100644 --- a/server/CServer.h +++ b/server/CServer.h @@ -14,7 +14,6 @@ class CClientProxy; class CHTTPServer; class CPrimaryClient; -class CThread; class IClient; class IDataSocket; class IServerProtocol; @@ -118,7 +117,7 @@ private: void closeClients(const CConfig& config); // start a thread, adding it to the list of threads - void startThread(IJob* adopted); + CThread startThread(IJob* adopted); // cancel running threads, waiting at most timeout seconds for // them to finish. @@ -171,6 +170,7 @@ private: // running threads CThreadList m_threads; + CThread* m_acceptClientThread; // the screens typedef std::map CClientList;