now cancelling and waiting for the accept client thread before

cancelling any other threads.  this prevents a race condition
where we disconnect a client but it reconnects before we
manage to shutdown.  that might leave a thread running and
the connection won't be closed down properly.
This commit is contained in:
crs 2002-07-18 17:00:48 +00:00
parent 0759cbc104
commit 635c3d1c62
2 changed files with 30 additions and 9 deletions

View File

@ -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<CServer>(this, &CServer::acceptClients));
m_acceptClientThread = new CThread(startThread(
new TMethodJob<CServer>(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;

View File

@ -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<CString, IClient*> CClientList;