diff --git a/client/CClient.cpp b/client/CClient.cpp index 1206176d..e2af4f15 100644 --- a/client/CClient.cpp +++ b/client/CClient.cpp @@ -52,25 +52,36 @@ CClient::camp(bool on) m_camp = on; } +bool +CClient::open() +{ + // open the screen + try { + log((CLOG_INFO "opening screen")); + openSecondaryScreen(); + return true; + } + catch (XScreenOpenFailure&) { + // can't open screen yet. wait a few seconds to retry. + CThread::sleep(3.0); + log((CLOG_INFO "failed to open screen")); + return false; + } +} + bool CClient::run(const CNetworkAddress& serverAddress) { + // check preconditions + { + CLock lock(&m_mutex); + assert(m_screen != NULL); + } + CThread* thread = NULL; try { log((CLOG_NOTE "starting client")); - // connect to secondary screen - while (m_screen == NULL) { - try { - openSecondaryScreen(); - } - catch (XScreenOpenFailure&) { - // can't open screen yet. wait a few seconds to retry. - log((CLOG_INFO "failed to open screen. waiting to retry.")); - CThread::sleep(3.0); - } - } - // start server interactions m_serverAddress = &serverAddress; thread = new CThread(new TMethodJob(this, &CClient::runSession)); @@ -108,9 +119,7 @@ CClient::run(const CNetworkAddress& serverAddress) thread->wait(); delete thread; } - if (m_screen != NULL) { - closeSecondaryScreen(); - } + closeSecondaryScreen(); throw; } catch (...) { @@ -123,9 +132,7 @@ CClient::run(const CNetworkAddress& serverAddress) thread->wait(); delete thread; } - if (m_screen != NULL) { - closeSecondaryScreen(); - } + closeSecondaryScreen(); throw; } } diff --git a/client/CClient.h b/client/CClient.h index d2dacc07..2a99d1ec 100644 --- a/client/CClient.h +++ b/client/CClient.h @@ -24,13 +24,17 @@ public: // not call this while in run(). void camp(bool on); + // open the client's screen + bool open(); + // start the client. does not return until quit() is called. // returns true if the client ever connected to the server // successfully. may also throw exceptions after successfully - // connecting. + // connecting. a successful open() must preceed this call. bool run(const CNetworkAddress& serverAddress); - // tell client to exit gracefully + // tell client to exit run() gracefully. this must only be called + // after a successful open(). void quit(); // handle events on client's screen diff --git a/client/CXWindowsSecondaryScreen.cpp b/client/CXWindowsSecondaryScreen.cpp index 60b0c0dc..ba881460 100644 --- a/client/CXWindowsSecondaryScreen.cpp +++ b/client/CXWindowsSecondaryScreen.cpp @@ -76,6 +76,7 @@ CXWindowsSecondaryScreen::run() void CXWindowsSecondaryScreen::stop() { + CDisplayLock display(this); doStop(); } diff --git a/client/client.cpp b/client/client.cpp index 9d4a13de..21d23b2d 100644 --- a/client/client.cpp +++ b/client/client.cpp @@ -81,6 +81,11 @@ realMain(CMutex* mutex) // create client s_client = new CClient(s_name); s_client->camp(s_camp); + if (!s_client->open()) { + delete s_client; + s_client = NULL; + return 16; + } // run client if (mutex != NULL) { @@ -96,7 +101,6 @@ realMain(CMutex* mutex) // clean up delete s_client; s_client = NULL; - CNetwork::cleanup(); CLog::setLock(NULL); s_logMutex = NULL; @@ -109,7 +113,6 @@ realMain(CMutex* mutex) } delete s_client; s_client = NULL; - CNetwork::cleanup(); CLog::setLock(NULL); s_logMutex = NULL; throw; @@ -602,6 +605,8 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) result = restartableMain(); } + CNetwork::cleanup(); + return result; } @@ -641,6 +646,8 @@ main(int argc, char** argv) result = restartableMain(); } + CNetwork::cleanup(); + return result; } diff --git a/server/CServer.cpp b/server/CServer.cpp index 22c79ee5..67b6d562 100644 --- a/server/CServer.cpp +++ b/server/CServer.cpp @@ -55,30 +55,41 @@ CServer::~CServer() // do nothing } +bool +CServer::open() +{ + // open the screen + try { + log((CLOG_INFO "opening screen")); + openPrimaryScreen(); + return true; + } + catch (XScreenOpenFailure&) { + // can't open screen yet. wait a few seconds to retry. + CThread::sleep(3.0); + log((CLOG_INFO "failed to open screen")); + return false; + } + catch (XUnknownClient& e) { + // can't open screen yet. wait a few seconds to retry. + CThread::sleep(3.0); + log((CLOG_CRIT "unknown screen name `%s'", e.getName().c_str())); + return false; + } +} + void CServer::run() { + // check preconditions + { + CLock lock(&m_mutex); + assert(m_primary != NULL); + } + try { log((CLOG_NOTE "starting server")); - // connect to primary screen - while (m_primary == NULL) { - try { - openPrimaryScreen(); - } - catch (XScreenOpenFailure&) { - // can't open screen yet. wait a few seconds to retry. - log((CLOG_INFO "failed to open screen. waiting to retry.")); - CThread::sleep(3.0); - } - catch (XUnknownClient& e) { - // can't open screen yet. wait a few seconds to retry. - log((CLOG_CRIT "unknown screen name `%s'", e.getName().c_str())); - log((CLOG_NOTE "stopping server")); - return; - } - } - // start listening for new clients startThread(new TMethodJob(this, &CServer::acceptClients)); diff --git a/server/CServer.h b/server/CServer.h index a4e64678..a589ecb4 100644 --- a/server/CServer.h +++ b/server/CServer.h @@ -27,10 +27,15 @@ public: // manipulators + // open the server's screen + bool open(); + // start the server. does not return until quit() is called. + // this must be preceeded by a successful call to open(). void run(); - // tell server to exit gracefully + // tell server to exit gracefully. this may only be called + // after a successful open(). void quit(); // tell the server to shutdown. this is called in an emergency diff --git a/server/server.cpp b/server/server.cpp index 18f55ec0..5e3ec8b3 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -113,13 +113,18 @@ realMain(CMutex* mutex) // create server s_server = new CServer(s_name); + s_server->setConfig(s_config); + if (!s_server->open()) { + delete s_server; + s_server = NULL; + return 16; + } // run server (unlocked) if (mutex != NULL) { mutex->unlock(); } locked = false; - s_server->setConfig(s_config); s_server->run(); locked = true; if (mutex != NULL) { @@ -129,7 +134,6 @@ realMain(CMutex* mutex) // clean up delete s_server; s_server = NULL; - CNetwork::cleanup(); CLog::setLock(NULL); s_logMutex = NULL; } @@ -140,7 +144,6 @@ realMain(CMutex* mutex) } delete s_server; s_server = NULL; - CNetwork::cleanup(); CLog::setLock(NULL); s_logMutex = NULL; throw; @@ -723,6 +726,8 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) result = restartableMain(); } + CNetwork::cleanup(); + return result; } @@ -765,6 +770,8 @@ main(int argc, char** argv) result = restartableMain(); } + CNetwork::cleanup(); + return result; }