Changed server to fail with an error if in can't bind() the listen

socket for any reason other than it's in use.
This commit is contained in:
crs 2002-10-17 21:37:31 +00:00
parent 586a5a81ab
commit 1d7f3d2aaf
2 changed files with 53 additions and 3 deletions

View File

@ -46,6 +46,7 @@ const SInt32 CServer::s_httpMaxSimultaneousRequests = 3;
CServer::CServer(const CString& serverName) : CServer::CServer(const CString& serverName) :
m_name(serverName), m_name(serverName),
m_error(false),
m_bindTimeout(5.0 * 60.0), m_bindTimeout(5.0 * 60.0),
m_screenFactory(NULL), m_screenFactory(NULL),
m_socketFactory(NULL), m_socketFactory(NULL),
@ -161,6 +162,12 @@ CServer::mainLoop()
throw; throw;
} }
#undef FINALLY #undef FINALLY
// throw if there was an error
if (m_error) {
LOG((CLOG_DEBUG "forwarding child thread exception"));
throw XServerRethrow();
}
} }
void void
@ -169,6 +176,16 @@ CServer::exitMainLoop()
m_primaryClient->exitMainLoop(); m_primaryClient->exitMainLoop();
} }
void
CServer::exitMainLoopWithError()
{
{
CLock lock(&m_mutex);
m_error = true;
}
exitMainLoop();
}
void void
CServer::close() CServer::close()
{ {
@ -1186,7 +1203,7 @@ CServer::acceptClients(void*)
listen->bind(m_config.getSynergyAddress()); listen->bind(m_config.getSynergyAddress());
break; break;
} }
catch (XSocketBind& e) { catch (XSocketAddressInUse& e) {
LOG((CLOG_WARN "bind failed: %s", e.getErrstr())); LOG((CLOG_WARN "bind failed: %s", e.getErrstr()));
// give up if we've waited too long // give up if we've waited too long
@ -1220,7 +1237,7 @@ CServer::acceptClients(void*)
catch (XBase& e) { catch (XBase& e) {
LOG((CLOG_ERR "cannot listen for clients: %s", e.what())); LOG((CLOG_ERR "cannot listen for clients: %s", e.what()));
delete listen; delete listen;
exitMainLoop(); exitMainLoopWithError();
} }
catch (...) { catch (...) {
delete listen; delete listen;
@ -1505,7 +1522,7 @@ CServer::acceptHTTPClients(void*)
catch (XBase& e) { catch (XBase& e) {
LOG((CLOG_ERR "cannot listen for HTTP clients: %s", e.what())); LOG((CLOG_ERR "cannot listen for HTTP clients: %s", e.what()));
delete listen; delete listen;
exitMainLoop(); exitMainLoopWithError();
} }
catch (...) { catch (...) {
delete listen; delete listen;
@ -1691,6 +1708,17 @@ CServer::removeConnection(const CString& name)
} }
//
// CServer::CClipboardInfo
//
CString
CServer::XServerRethrow::getWhat() const throw()
{
return format("XServerRethrow", "child thread failed");
}
// //
// CServer::CClipboardInfo // CServer::CClipboardInfo
// //

View File

@ -157,6 +157,14 @@ protected:
*/ */
bool onCommandKey(KeyID, KeyModifierMask, bool down); bool onCommandKey(KeyID, KeyModifierMask, bool down);
//! Exit event loop and note an error condition
/*!
Force mainLoop() to return by throwing an exception. This call
can return before mainLoop() does (i.e. asynchronously). This
may only be called between a successful open() and close().
*/
void exitMainLoopWithError();
private: private:
typedef std::list<CThread> CThreadList; typedef std::list<CThread> CThreadList;
@ -230,6 +238,12 @@ private:
void removeConnection(const CString& name); void removeConnection(const CString& name);
private: private:
class XServerRethrow : public XBase {
protected:
// XBase overrides
virtual CString getWhat() const throw();
};
class CClipboardInfo { class CClipboardInfo {
public: public:
CClipboardInfo(); CClipboardInfo();
@ -246,6 +260,14 @@ private:
// the name of the primary screen // the name of the primary screen
CString m_name; CString m_name;
// true if we should exit the main loop by throwing an exception.
// this is used to propagate an exception from one of our threads
// to the mainLoop() thread. but, since we can't make a copy of
// the original exception, we return an arbitrary, unique
// exception type. the caller of mainLoop() cannot catch this
// exception except through XBase or ....
bool m_error;
// how long to wait to bind our socket until we give up // how long to wait to bind our socket until we give up
double m_bindTimeout; double m_bindTimeout;