fixed problem with opening client and server. in some cases it

would fail to open in such a way that it could never succeed
but it'd never stop retrying.  now terminating when open fails
such that it'll never succeed.
This commit is contained in:
crs 2002-07-31 12:39:34 +00:00
parent f5795a6630
commit 5e40de48f9
18 changed files with 141 additions and 59 deletions

View File

@ -3,6 +3,7 @@
#include "CPlatform.h" #include "CPlatform.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "Version.h" #include "Version.h"
#include "XScreen.h"
#include "CNetwork.h" #include "CNetwork.h"
#include "CNetworkAddress.h" #include "CNetworkAddress.h"
#include "CTCPSocketFactory.h" #include "CTCPSocketFactory.h"
@ -125,7 +126,8 @@ realMain(CMutex* mutex)
s_client->setStreamFilterFactory(NULL); s_client->setStreamFilterFactory(NULL);
// open client // open client
if (s_client->open()) { try {
s_client->open();
opened = true; opened = true;
// run client // run client
@ -139,31 +141,33 @@ realMain(CMutex* mutex)
mutex->lock(); mutex->lock();
} }
// get client status
if (s_client->wasRejected()) {
// wait a while before retrying. we don't want
// to bother the server very often if it doesn't
// want us.
if (s_restartable) {
CThread::sleep(60.0);
}
else {
result = kExitFailed;
}
}
// clean up // clean up
s_client->close(); s_client->close();
// get client status
if (s_client->wasRejected()) {
// try again later. we don't want to bother
// the server very often if it doesn't want us.
throw XScreenUnavailable(60.0);
}
} }
else { catch (XScreenUnavailable& e) {
// wait a few seconds before retrying // wait a few seconds before retrying
if (s_restartable) { if (s_restartable) {
CThread::sleep(3.0); CThread::sleep(e.getRetryTime());
} }
else { else {
result = kExitFailed; result = kExitFailed;
} }
} }
catch (...) {
// rethrow thread exceptions
RETHROW_XTHREAD
// don't try to restart and fail
s_restartable = false;
result = kExitFailed;
}
// clean up // clean up
delete s_client; delete s_client;

View File

@ -4,6 +4,7 @@
#include "CPlatform.h" #include "CPlatform.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "Version.h" #include "Version.h"
#include "XScreen.h"
#include "CNetwork.h" #include "CNetwork.h"
#include "CTCPSocketFactory.h" #include "CTCPSocketFactory.h"
#include "XSocket.h" #include "XSocket.h"
@ -156,7 +157,8 @@ realMain(CMutex* mutex)
s_server->setStreamFilterFactory(NULL); s_server->setStreamFilterFactory(NULL);
// open server // open server
if (s_server->open()) { try {
s_server->open();
opened = true; opened = true;
// run server (unlocked) // run server (unlocked)
@ -173,15 +175,23 @@ realMain(CMutex* mutex)
// clean up // clean up
s_server->close(); s_server->close();
} }
else { catch (XScreenUnavailable& e) {
// wait a few seconds before retrying // wait before retrying if we're going to retry
if (s_restartable) { if (s_restartable) {
CThread::sleep(3.0); CThread::sleep(e.getRetryTime());
} }
else { else {
result = kExitFailed; result = kExitFailed;
} }
} }
catch (...) {
// rethrow thread exceptions
RETHROW_XTHREAD
// don't try to restart and fail
s_restartable = false;
result = kExitFailed;
}
// clean up // clean up
delete s_server; delete s_server;

View File

@ -149,19 +149,18 @@ CClient::onClipboardChanged(ClipboardID, const CString&)
// ignore -- we'll check the clipboard when we leave // ignore -- we'll check the clipboard when we leave
} }
bool void
CClient::open() CClient::open()
{ {
// open the screen // open the screen
try { try {
log((CLOG_INFO "opening screen")); log((CLOG_INFO "opening screen"));
openSecondaryScreen(); openSecondaryScreen();
return true;
} }
catch (XScreenOpenFailure&) { catch (XScreenOpenFailure&) {
// can't open screen yet. wait a few seconds to retry. // can't open screen
log((CLOG_INFO "failed to open screen")); log((CLOG_INFO "failed to open screen"));
return false; throw;
} }
} }
@ -368,7 +367,6 @@ void
CClient::openSecondaryScreen() CClient::openSecondaryScreen()
{ {
assert(m_screen == NULL); assert(m_screen == NULL);
assert(m_screenFactory != NULL);
// not active // not active
m_active = false; m_active = false;
@ -381,7 +379,9 @@ CClient::openSecondaryScreen()
// create screen // create screen
log((CLOG_DEBUG1 "creating secondary screen")); log((CLOG_DEBUG1 "creating secondary screen"));
m_screen = m_screenFactory->create(this); if (m_screenFactory != NULL) {
m_screen = m_screenFactory->create(this);
}
if (m_screen == NULL) { if (m_screen == NULL) {
throw XScreenOpenFailure(); throw XScreenOpenFailure();
} }
@ -402,12 +402,12 @@ CClient::openSecondaryScreen()
void void
CClient::closeSecondaryScreen() CClient::closeSecondaryScreen()
{ {
assert(m_screen != NULL);
// close the secondary screen // close the secondary screen
try { try {
log((CLOG_DEBUG1 "closing secondary screen")); if (m_screen != NULL) {
m_screen->close(); log((CLOG_DEBUG1 "closing secondary screen"));
m_screen->close();
}
} }
catch (...) { catch (...) {
// ignore // ignore

View File

@ -98,7 +98,7 @@ public:
virtual void onClipboardChanged(ClipboardID, const CString&); virtual void onClipboardChanged(ClipboardID, const CString&);
// IClient overrides // IClient overrides
virtual bool open(); virtual void open();
virtual void mainLoop(); virtual void mainLoop();
virtual void close(); virtual void close();
virtual void enter(SInt32 xAbs, SInt32 yAbs, virtual void enter(SInt32 xAbs, SInt32 yAbs,

View File

@ -229,7 +229,7 @@ CXWindowsSecondaryScreen::createWindow()
int majorOpcode, firstEvent, firstError; int majorOpcode, firstEvent, firstError;
if (!XQueryExtension(display, XTestExtensionName, if (!XQueryExtension(display, XTestExtensionName,
&majorOpcode, &firstEvent, &firstError)) { &majorOpcode, &firstEvent, &firstError)) {
// FIXME -- subclass exception for more info? log((CLOG_ERR "XTEST extension not available"));
throw XScreenOpenFailure(); throw XScreenOpenFailure();
} }

View File

@ -197,7 +197,7 @@ CXWindowsScreen::open()
log((CLOG_DEBUG "XOpenDisplay(\"%s\")", display)); log((CLOG_DEBUG "XOpenDisplay(\"%s\")", display));
m_display = XOpenDisplay(display); m_display = XOpenDisplay(display);
if (m_display == NULL) { if (m_display == NULL) {
throw XScreenOpenFailure(); throw XScreenUnavailable(60.0);
} }
// get root window // get root window

View File

@ -43,7 +43,7 @@ public:
//@} //@}
// IClient overrides // IClient overrides
virtual bool open() = 0; virtual void open() = 0;
virtual void mainLoop() = 0; virtual void mainLoop() = 0;
virtual void close() = 0; virtual void close() = 0;
virtual void enter(SInt32 xAbs, SInt32 yAbs, virtual void enter(SInt32 xAbs, SInt32 yAbs,

View File

@ -29,7 +29,7 @@ CClientProxy1_0::~CClientProxy1_0()
// do nothing // do nothing
} }
bool void
CClientProxy1_0::open() CClientProxy1_0::open()
{ {
// send request // send request
@ -55,8 +55,6 @@ CClientProxy1_0::open()
// handle reply // handle reply
recvInfo(false); recvInfo(false);
return true;
} }
void void

View File

@ -14,7 +14,7 @@ public:
~CClientProxy1_0(); ~CClientProxy1_0();
// IClient overrides // IClient overrides
virtual bool open(); virtual void open();
virtual void mainLoop(); virtual void mainLoop();
virtual void close(); virtual void close();
virtual void enter(SInt32 xAbs, SInt32 yAbs, virtual void enter(SInt32 xAbs, SInt32 yAbs,

View File

@ -399,6 +399,7 @@ CMSWindowsPrimaryScreen::onPreOpen()
// initialize hook library // initialize hook library
m_threadID = GetCurrentThreadId(); m_threadID = GetCurrentThreadId();
if (m_init(m_threadID) == 0) { if (m_init(m_threadID) == 0) {
log((CLOG_ERR "cannot initialize hook library"));
throw XScreenOpenFailure(); throw XScreenOpenFailure();
} }
} }

View File

@ -1,6 +1,7 @@
#include "CPrimaryClient.h" #include "CPrimaryClient.h"
#include "IPrimaryScreenFactory.h" #include "IPrimaryScreenFactory.h"
#include "IServer.h" #include "IServer.h"
#include "XScreen.h"
#include "XSynergy.h" #include "XSynergy.h"
#include "CPrimaryScreen.h" #include "CPrimaryScreen.h"
#include "CClipboard.h" #include "CClipboard.h"
@ -19,11 +20,15 @@ CPrimaryClient::CPrimaryClient(IPrimaryScreenFactory* screenFactory,
m_seqNum(0) m_seqNum(0)
{ {
assert(m_server != NULL); assert(m_server != NULL);
assert(screenFactory != NULL);
// create screen // create screen
log((CLOG_DEBUG1 "creating primary screen")); log((CLOG_DEBUG1 "creating primary screen"));
m_screen = screenFactory->create(this, receiver); if (screenFactory != NULL) {
m_screen = screenFactory->create(this, receiver);
}
if (m_screen == NULL) {
throw XScreenOpenFailure();
}
} }
CPrimaryClient::~CPrimaryClient() CPrimaryClient::~CPrimaryClient()
@ -100,7 +105,7 @@ CPrimaryClient::onClipboardChanged(ClipboardID id, const CString& data)
m_server->onClipboardChanged(id, m_seqNum, data); m_server->onClipboardChanged(id, m_seqNum, data);
} }
bool void
CPrimaryClient::open() CPrimaryClient::open()
{ {
// all clipboards are clean // all clipboards are clean
@ -110,8 +115,6 @@ CPrimaryClient::open()
// now open the screen // now open the screen
m_screen->open(); m_screen->open();
return true;
} }
void void

View File

@ -20,8 +20,9 @@ treated as if it was on a client.
class CPrimaryClient : public IScreenReceiver, public IClient { class CPrimaryClient : public IScreenReceiver, public IClient {
public: public:
/*! /*!
\c name is the name of the server. the caller retains ownership of \c name is the name of the server. The caller retains ownership of
\c factory. \c factory. Throws XScreenOpenFailure or whatever the factory can
throw if the screen cannot be created.
*/ */
CPrimaryClient(IPrimaryScreenFactory* factory, IServer*, CPrimaryClient(IPrimaryScreenFactory* factory, IServer*,
IPrimaryScreenReceiver*, const CString& name); IPrimaryScreenReceiver*, const CString& name);
@ -75,7 +76,7 @@ public:
virtual void onClipboardChanged(ClipboardID, const CString&); virtual void onClipboardChanged(ClipboardID, const CString&);
// IClient overrides // IClient overrides
virtual bool open(); virtual void open();
virtual void mainLoop(); virtual void mainLoop();
virtual void close(); virtual void close();
virtual void enter(SInt32 xAbs, SInt32 yAbs, virtual void enter(SInt32 xAbs, SInt32 yAbs,

View File

@ -53,24 +53,23 @@ CServer::~CServer()
delete m_streamFilterFactory; delete m_streamFilterFactory;
} }
bool void
CServer::open() CServer::open()
{ {
// open the screen // open the screen
try { try {
log((CLOG_INFO "opening screen")); log((CLOG_INFO "opening screen"));
openPrimaryScreen(); openPrimaryScreen();
return true;
} }
catch (XScreenOpenFailure&) { catch (XScreen&) {
// can't open screen yet. wait a few seconds to retry. // can't open screen
log((CLOG_INFO "failed to open screen")); log((CLOG_INFO "failed to open screen"));
return false; throw;
} }
catch (XUnknownClient& e) { catch (XUnknownClient& e) {
// can't open screen yet. wait a few seconds to retry. // can't open screen
log((CLOG_CRIT "unknown screen name `%s'", e.getName().c_str())); log((CLOG_CRIT "unknown screen name `%s'", e.getName().c_str()));
return false; throw;
} }
} }
@ -1529,7 +1528,6 @@ void
CServer::openPrimaryScreen() CServer::openPrimaryScreen()
{ {
assert(m_primaryClient == NULL); assert(m_primaryClient == NULL);
assert(m_screenFactory != NULL);
// reset sequence number // reset sequence number
m_seqNum = 0; m_seqNum = 0;

View File

@ -39,9 +39,12 @@ public:
//! Open server //! Open server
/*! /*!
Open the server and return true iff successful. Open the server. Throws XScreenUnavailable if the server's
screen cannot be opened but might be available after some time.
Otherwise throws some other exception if the server's screen or
the server cannot be opened and retrying won't help.
*/ */
bool open(); void open();
//! Server main loop //! Server main loop
/*! /*!

View File

@ -19,9 +19,11 @@ public:
//! Open client //! Open client
/*! /*!
Open the client and return true iff successful. Open the client. Throw if the client cannot be opened. If the
screen cannot be opened but retrying later may succeed then throw
XScreenUnavailable.
*/ */
virtual bool open() = 0; virtual void open() = 0;
//! Client main loop //! Client main loop
/*! /*!

View File

@ -19,7 +19,9 @@ public:
//! Open screen //! Open screen
/*! /*!
Called to open and initialize the screen. Called to open and initialize the screen. Throw XScreenUnavailable
if the screen cannot be opened but retrying later may succeed.
Otherwise throw some other XScreenOpenFailure exception.
*/ */
virtual void open() = 0; virtual void open() = 0;

View File

@ -9,3 +9,31 @@ XScreenOpenFailure::getWhat() const throw()
{ {
return format("XScreenOpenFailure", "unable to open screen"); return format("XScreenOpenFailure", "unable to open screen");
} }
//
// XScreenUnavailable
//
XScreenUnavailable::XScreenUnavailable(double timeUntilRetry) :
m_timeUntilRetry(timeUntilRetry)
{
// do nothing
}
XScreenUnavailable::~XScreenUnavailable()
{
// do nothing
}
double
XScreenUnavailable::getRetryTime() const
{
return m_timeUntilRetry;
}
CString
XScreenUnavailable::getWhat() const throw()
{
return format("XScreenUnavailable", "unable to open screen");
}

View File

@ -15,4 +15,36 @@ protected:
virtual CString getWhat() const throw(); virtual CString getWhat() const throw();
}; };
//! Screen unavailable exception
/*!
Thrown when a screen cannot be opened or initialized but retrying later
may be successful.
*/
class XScreenUnavailable : public XScreenOpenFailure {
public:
/*!
\c timeUntilRetry is the suggested time the caller should wait until
trying to open the screen again.
*/
XScreenUnavailable(double timeUntilRetry);
virtual ~XScreenUnavailable();
//! @name manipulators
//@{
//! Get retry time
/*!
Returns the suggested time to wait until retrying to open the screen.
*/
double getRetryTime() const;
//@}
protected:
virtual CString getWhat() const throw();
private:
double m_timeUntilRetry;
};
#endif #endif