diff --git a/client/CClient.cpp b/client/CClient.cpp index 7c2d5fa4..6efa48b0 100644 --- a/client/CClient.cpp +++ b/client/CClient.cpp @@ -127,7 +127,6 @@ CClient::open() } 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; } @@ -360,7 +359,15 @@ CClient::openSecondaryScreen() m_screen = new CXWindowsSecondaryScreen(this); #endif log((CLOG_DEBUG1 "opening secondary screen")); - m_screen->open(); + try { + m_screen->open(); + } + catch (...) { + log((CLOG_DEBUG1 "destroying secondary screen")); + delete m_screen; + m_screen = NULL; + throw; + } } void @@ -472,7 +479,9 @@ CClient::runServer() log((CLOG_INFO "connected to server")); break; } - catch (XSocketConnect&) { + catch (XSocketConnect& e) { + log((CLOG_DEBUG1 "failed to connect to server: %s", e.getErrstr())); + // failed to connect. if not camping then rethrow. if (!m_camp) { throw; diff --git a/client/client.cpp b/client/client.cpp index cda8e0a9..0bda2676 100644 --- a/client/client.cpp +++ b/client/client.cpp @@ -67,95 +67,99 @@ static int realMain(CMutex* mutex) { - try { - // initialize threading library - CThread::init(); + // caller should have mutex locked on entry - // make logging thread safe - CMutex logMutex; - s_logMutex = &logMutex; - CLog::setLock(&logLock); - - bool locked = true; + int result = kExitSuccess; + do { try { - // create client - s_client = new CClient(s_name); - s_client->camp(s_camp); - s_client->setAddress(s_serverAddress); - if (!s_client->open()) { + // initialize threading library + CThread::init(); + + // make logging thread safe + CMutex logMutex; + s_logMutex = &logMutex; + CLog::setLock(&logLock); + + bool opened = false; + bool locked = true; + try { + // create client + s_client = new CClient(s_name); + s_client->camp(s_camp); + s_client->setAddress(s_serverAddress); + if (s_client->open()) { + opened = true; + + // run client + if (mutex != NULL) { + mutex->unlock(); + } + locked = false; + s_client->run(); + locked = true; + if (mutex != NULL) { + 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 + s_client->close(); + } + else { + // wait a few seconds before retrying + if (s_restartable) { + CThread::sleep(3.0); + } + else { + result = kExitFailed; + } + } + + // clean up delete s_client; s_client = NULL; - return 16; + CLog::setLock(NULL); + s_logMutex = NULL; } - - // run client - if (mutex != NULL) { - mutex->unlock(); + catch (...) { + // clean up + if (!locked && mutex != NULL) { + mutex->lock(); + } + if (s_client != NULL) { + if (opened) { + s_client->close(); + } + delete s_client; + s_client = NULL; + } + CLog::setLock(NULL); + s_logMutex = NULL; + throw; } - locked = false; - s_client->run(); - locked = true; - if (mutex != NULL) { - mutex->lock(); - } - - // get client status - bool success = !s_client->wasRejected(); - - // clean up - s_client->close(); - delete s_client; - s_client = NULL; - CLog::setLock(NULL); - s_logMutex = NULL; - - return success ? 16 : 0; } - catch (...) { - // clean up - if (!locked && mutex != NULL) { - mutex->lock(); - } - if (s_client != NULL) { - s_client->close(); - delete s_client; - s_client = NULL; - } - CLog::setLock(NULL); - s_logMutex = NULL; - throw; + catch (XBase& e) { + log((CLOG_CRIT "failed: %s", e.what())); } - } - catch (XBase& e) { - log((CLOG_CRIT "failed: %s", e.what())); - return 16; - } - catch (XThread&) { - // terminated - return 1; - } -} + catch (XThread&) { + // terminated + return kExitTerminated; + } + } while (s_restartable); -static -int -restartMain() -{ - return realMain(NULL); -} - -// invoke realMain and wait for it. if s_restartable then keep -// restarting realMain until it returns a terminate code. -static -int -restartableMain() -{ - if (s_restartable) { - CPlatform platform; - return platform.restart(restartMain, 16); - } - else { - return realMain(NULL); - } + return result; } @@ -229,10 +233,7 @@ PLATFORM_ARGS " ourself to the server.\n" " -1, --no-restart do not try to restart the client if it fails for\n" " some reason.\n" -"* --restart restart the client automatically if it fails for\n" -" some unexpected reason, including the server\n" -" disconnecting but not including failing to\n" -" connect to the server.\n" +"* --restart restart the client automatically if it fails.\n" PLATFORM_DESC " -h, --help display this help and exit.\n" " --version display version information and exit.\n" @@ -261,7 +262,7 @@ isArg(int argi, int argc, const char** argv, if (argi + minRequiredParameters >= argc) { log((CLOG_PRINT "%s: missing arguments for `%s'" BYE, pname, argv[argi], pname)); - bye(2); + bye(kExitArgs); } return true; } @@ -329,12 +330,12 @@ parse(int argc, const char** argv) else if (isArg(i, argc, argv, "-h", "--help")) { help(); - bye(0); + bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--version")) { version(); - bye(0); + bye(kExitSuccess); } #if WINDOWS_LIKE @@ -344,7 +345,7 @@ parse(int argc, const char** argv) log((CLOG_PRINT "%s: `--install' and `--uninstall'" " are mutually exclusive" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } } #endif @@ -356,7 +357,7 @@ parse(int argc, const char** argv) log((CLOG_PRINT "%s: `--install' and `--uninstall'" " are mutually exclusive" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } } #endif @@ -370,7 +371,7 @@ parse(int argc, const char** argv) else if (argv[i][0] == '-') { log((CLOG_PRINT "%s: unrecognized option `%s'" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } else { @@ -386,19 +387,19 @@ parse(int argc, const char** argv) log((CLOG_PRINT "%s: unrecognized option `%s' to `%s'" BYE, pname, argv[i], pname, s_install ? "--install" : "--uninstall")); - bye(2); + bye(kExitArgs); } } else { if (i == argc) { log((CLOG_PRINT "%s: a server address or name is required" BYE, pname, pname)); - bye(1); + bye(kExitArgs); } if (i + 1 != argc) { log((CLOG_PRINT "%s: unrecognized option `%s'" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } // save server address @@ -408,7 +409,7 @@ parse(int argc, const char** argv) catch (XSocketAddress&) { log((CLOG_PRINT "%s: invalid server address" BYE, pname, pname)); - bye(2); + bye(kExitArgs); } } @@ -432,7 +433,7 @@ parse(int argc, const char** argv) if (!CLog::setFilter(s_logFilter)) { log((CLOG_PRINT "%s: unrecognized log level `%s'" BYE, pname, s_logFilter, pname)); - bye(2); + bye(kExitArgs); } } @@ -488,7 +489,7 @@ daemonStartup(IPlatform* iplatform, int argc, const char** argv) parse(argc, argv); if (s_install || s_uninstall) { // not allowed to install/uninstall from service - throw CWin32Platform::CDaemonFailed(1); + throw CWin32Platform::CDaemonFailed(kExitArgs); } // run as a service @@ -499,7 +500,7 @@ static int daemonStartup95(IPlatform*, int, const char**) { - return restartableMain(); + return realMain(NULL); } int WINAPI @@ -529,7 +530,7 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) int result = platform.daemonize(DAEMON_NAME, &daemonStartup); if (result == -1) { log((CLOG_CRIT "failed to start as a service" BYE, pname)); - return 16; + return kExitFailed; } return result; } @@ -544,7 +545,7 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) if (GetModuleFileName(NULL, path, sizeof(path) / sizeof(path[0])) == 0) { log((CLOG_CRIT "cannot determine absolute path to program")); - return 16; + return kExitFailed; } // construct the command line to start the service with @@ -567,24 +568,24 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) "Shares this system's mouse and keyboard with others.", path, commandLine.c_str())) { log((CLOG_CRIT "failed to install service")); - return 16; + return kExitFailed; } log((CLOG_PRINT "installed successfully")); - return 0; + return kExitSuccess; } else if (s_uninstall) { switch (platform.uninstallDaemon(DAEMON_NAME)) { case IPlatform::kSuccess: log((CLOG_PRINT "uninstalled successfully")); - return 0; + return kExitSuccess; case IPlatform::kFailed: log((CLOG_CRIT "failed to uninstall service")); - return 16; + return kExitFailed; case IPlatform::kAlready: log((CLOG_CRIT "service isn't installed")); - return 16; + return kExitFailed; } } @@ -599,18 +600,18 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) result = platform.daemonize(DAEMON_NAME, &daemonStartup95); if (result == -1) { log((CLOG_CRIT "failed to start as a service" BYE, pname)); - return 16; + return kExitFailed; } } else { // cannot start a service from the command line so just // run normally (except with log messages redirected). - result = restartableMain(); + result = realMain(NULL); } } else { // run - result = restartableMain(); + result = realMain(NULL); } CNetwork::cleanup(); @@ -624,7 +625,7 @@ static int daemonStartup(IPlatform*, int, const char**) { - return restartableMain(); + return realMain(NULL); } int @@ -647,11 +648,11 @@ main(int argc, char** argv) result = platform.daemonize(DAEMON_NAME, &daemonStartup); if (result == -1) { log((CLOG_CRIT "failed to daemonize")); - return 16; + return kExitFailed; } } else { - result = restartableMain(); + result = realMain(NULL); } CNetwork::cleanup(); diff --git a/net/CTCPSocket.cpp b/net/CTCPSocket.cpp index c6e1970e..35a51244 100644 --- a/net/CTCPSocket.cpp +++ b/net/CTCPSocket.cpp @@ -115,8 +115,9 @@ CTCPSocket::connect(const CNetworkAddress& addr) addr.getAddressLength()) == CNetwork::Error) { // check for failure if (CNetwork::getsockerror() != CNetwork::kECONNECTING) { + XSocketConnect e; CNetwork::setblocking(m_fd, true); - throw XSocketConnect(); + throw e; } // wait for connection or failure @@ -130,8 +131,12 @@ CTCPSocket::connect(const CNetworkAddress& addr) if ((pfds[0].revents & (CNetwork::kPOLLERR | CNetwork::kPOLLNVAL)) != 0) { // connection failed + int error = 0; + CNetwork::AddressLength size = sizeof(error); CNetwork::setblocking(m_fd, true); - throw XSocketConnect(); + CNetwork::getsockopt(m_fd, SOL_SOCKET, SO_ERROR, + reinterpret_cast(&error), &size); + throw XSocketConnect(error); } if ((pfds[0].revents & CNetwork::kPOLLOUT) != 0) { int error; @@ -142,7 +147,7 @@ CTCPSocket::connect(const CNetworkAddress& addr) error != 0) { // connection failed CNetwork::setblocking(m_fd, true); - throw XSocketConnect(); + throw XSocketConnect(error); } // connected! diff --git a/net/XSocket.h b/net/XSocket.h index 4b0fbf7c..354e57af 100644 --- a/net/XSocket.h +++ b/net/XSocket.h @@ -36,20 +36,36 @@ public: }; class XSocketBind : public XSocketErrno { +public: + XSocketBind() { } + XSocketBind(int e) : XSocketErrno(e) { } + protected: // XBase overrides virtual CString getWhat() const throw(); }; -class XSocketAddressInUse : public XSocketBind { }; +class XSocketAddressInUse : public XSocketBind { +public: + XSocketAddressInUse() { } + XSocketAddressInUse(int e) : XSocketBind(e) { } +}; class XSocketConnect : public XSocketErrno { +public: + XSocketConnect() { } + XSocketConnect(int e) : XSocketErrno(e) { } + protected: // XBase overrides virtual CString getWhat() const throw(); }; class XSocketCreate : public XSocketErrno { +public: + XSocketCreate() { } + XSocketCreate(int e) : XSocketErrno(e) { } + protected: // XBase overrides virtual CString getWhat() const throw(); diff --git a/platform/CUnixPlatform.cpp b/platform/CUnixPlatform.cpp index c1210458..9e3c10e2 100644 --- a/platform/CUnixPlatform.cpp +++ b/platform/CUnixPlatform.cpp @@ -7,22 +7,6 @@ #include #include #include -#include -#if HAVE_SYS_WAIT_H -# include -#endif -#if !defined(WIFSIGNALED) -# define WIFSIGNALED(w) (((w) & 0xff) != 0x7f && ((w) & 0xff) != 0) -#endif -#if !defined(WIFEXITED) -# define WIFEXITED(w) (((w) & 0xff) == 0) -#endif -#if !defined(WTERMSIG) -# define WTERMSIG(w) ((w) & 0x7f) -#endif -#if !defined(WEXITSTATUS) -# define WEXITSTATUS(w) (((w) >> 8) & 0xff) -#endif // @@ -106,64 +90,6 @@ CUnixPlatform::installDaemonLogger(const char* name) CLog::setOutputter(&CUnixPlatform::deamonLogger); } -int -CUnixPlatform::restart(RestartFunc func, int minErrorCode) -{ - // rely on child to catch these signals - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGINT); - sigaddset(&sigset, SIGTERM); - pthread_sigmask(SIG_BLOCK, &sigset, NULL); - - for (;;) { - switch (fork()) { - default: - { - // parent process. wait for child to exit. - int status; - if (wait(&status) == -1) { - // wait failed. this is unexpected so bail. - log((CLOG_CRIT "wait() failed")); - return minErrorCode; - } - - // what happened? if the child exited normally with a - // status less than 16 then the child was deliberately - // terminated so we also terminate. - if (WIFEXITED(status) && WEXITSTATUS(status) < minErrorCode) { - return WEXITSTATUS(status); - } - - // did child die horribly? - if (WIFSIGNALED(status)) { - switch (WTERMSIG(status)) { - case SIGHUP: - case SIGINT: - case SIGQUIT: - case SIGTERM: - break; - - default: - // uh oh. bail out. - return 16; - } - } - } - break; - - case -1: - // fork() failed. log the error and proceed as a child - log((CLOG_WARN "fork() failed; cannot automatically restart on error")); - // fall through - - case 0: - // child process - return func(); - } - } -} - const char* CUnixPlatform::getBasename(const char* pathname) const { diff --git a/platform/CUnixPlatform.h b/platform/CUnixPlatform.h index 9b5592b4..8fbe56c9 100644 --- a/platform/CUnixPlatform.h +++ b/platform/CUnixPlatform.h @@ -16,7 +16,6 @@ public: virtual EResult uninstallDaemon(const char* name); virtual int daemonize(const char* name, DaemonFunc); virtual void installDaemonLogger(const char* name); - virtual int restart(RestartFunc, int minErrorCode); virtual const char* getBasename(const char* pathname) const; virtual CString getUserDirectory() const; virtual CString getSystemDirectory() const; diff --git a/platform/CWin32Platform.cpp b/platform/CWin32Platform.cpp index 440ddccc..3553c38a 100644 --- a/platform/CWin32Platform.cpp +++ b/platform/CWin32Platform.cpp @@ -319,15 +319,6 @@ CWin32Platform::installDaemonLogger(const char* name) } } -int -CWin32Platform::restart(RestartFunc func, int /*minErrorCode*/) -{ - // FIXME -- start in separate process or thread. note that this - // isn't too critical as win32 doesn't force us to terminate for - // any reason so we should never have to restart. - return func(); -} - const char* CWin32Platform::getBasename(const char* pathname) const { diff --git a/platform/CWin32Platform.h b/platform/CWin32Platform.h index 45f99e29..0fed1011 100644 --- a/platform/CWin32Platform.h +++ b/platform/CWin32Platform.h @@ -49,7 +49,6 @@ public: virtual EResult uninstallDaemon(const char* name); virtual int daemonize(const char* name, DaemonFunc); virtual void installDaemonLogger(const char* name); - virtual int restart(RestartFunc, int minErrorCode); virtual const char* getBasename(const char* pathname) const; virtual CString getUserDirectory() const; virtual CString getSystemDirectory() const; diff --git a/platform/CXWindowsScreen.cpp b/platform/CXWindowsScreen.cpp index 5ae7f31e..ae1936f5 100644 --- a/platform/CXWindowsScreen.cpp +++ b/platform/CXWindowsScreen.cpp @@ -93,6 +93,11 @@ CXWindowsScreen::CXWindowsScreen(IScreenReceiver* receiver, assert(m_eventHandler != NULL); s_screen = this; + + // no clipboards to start with + for (ClipboardID id = 0; id < kClipboardEnd; ++id) { + m_clipboard[id] = NULL; + } } CXWindowsScreen::~CXWindowsScreen() @@ -670,7 +675,10 @@ CDisplayLock::CDisplayLock(const CXWindowsScreen* screen) : m_mutex(&screen->m_mutex), m_display(screen->m_display) { - assert(m_display != NULL); + // note -- it's permitted for m_display to be NULL. that might + // happen if we couldn't connect to the display or if the + // display unexpectedly disconnected. the caller is expected + // to check for NULL as necessary. m_mutex->lock(); } diff --git a/platform/CXWindowsUtil.cpp b/platform/CXWindowsUtil.cpp index 253a3362..f65fe020 100644 --- a/platform/CXWindowsUtil.cpp +++ b/platform/CXWindowsUtil.cpp @@ -206,7 +206,9 @@ CXWindowsUtil::CErrorLock::CErrorLock(Display* display, CXWindowsUtil::CErrorLock::~CErrorLock() { // make sure everything finishes before uninstalling handler - XSync(m_display, False); + if (m_display != NULL) { + XSync(m_display, False); + } // restore old handler XSetErrorHandler(m_oldXHandler); @@ -217,7 +219,9 @@ void CXWindowsUtil::CErrorLock::install(ErrorHandler handler, void* data) { // make sure everything finishes before installing handler - XSync(m_display, False); + if (m_display != NULL) { + XSync(m_display, False); + } // install handler m_handler = handler; diff --git a/platform/IPlatform.h b/platform/IPlatform.h index 0a7e4cee..60056575 100644 --- a/platform/IPlatform.h +++ b/platform/IPlatform.h @@ -7,7 +7,6 @@ class IPlatform : public IInterface { public: typedef int (*DaemonFunc)(IPlatform*, int argc, const char** argv); - typedef int (*RestartFunc)(); enum EResult { kSuccess, @@ -53,11 +52,6 @@ public: // in the log to identify this process. virtual void installDaemonLogger(const char* name) = 0; - // continually restart the given function in a separate process - // or thread until it exits normally with a code less than the - // given code then return the code. - virtual int restart(RestartFunc, int minErrorCode) = 0; - // accessors // find the basename in the given pathname diff --git a/server/CPrimaryClient.cpp b/server/CPrimaryClient.cpp index 56bd3464..236fd57c 100644 --- a/server/CPrimaryClient.cpp +++ b/server/CPrimaryClient.cpp @@ -34,6 +34,7 @@ CPrimaryClient::CPrimaryClient(IServer* server, CPrimaryClient::~CPrimaryClient() { + log((CLOG_DEBUG1 "destroying primary screen")); delete m_screen; } diff --git a/server/CServer.cpp b/server/CServer.cpp index 89ff7150..9c4f3467 100644 --- a/server/CServer.cpp +++ b/server/CServer.cpp @@ -59,13 +59,11 @@ CServer::open() } 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; } @@ -1135,7 +1133,9 @@ CServer::acceptClients(void*) listen->bind(m_config.getSynergyAddress()); break; } - catch (XSocketAddressInUse&) { + catch (XSocketBind& e) { + log((CLOG_DEBUG1 "bind failed: %s", e.getErrstr())); + // give up if we've waited too long if (timer.getTime() >= m_bindTimeout) { log((CLOG_DEBUG1 "waited too long to bind, giving up")); @@ -1143,7 +1143,6 @@ CServer::acceptClients(void*) } // wait a bit before retrying - log((CLOG_DEBUG1 "bind failed; waiting to retry")); CThread::sleep(5.0); } } @@ -1419,7 +1418,9 @@ CServer::acceptHTTPClients(void*) listen->bind(m_config.getHTTPAddress()); break; } - catch (XSocketAddressInUse&) { + catch (XSocketBind& e) { + log((CLOG_DEBUG1 "bind HTTP failed: %s", e.getErrstr())); + // give up if we've waited too long if (timer.getTime() >= m_bindTimeout) { log((CLOG_DEBUG1 "waited too long to bind HTTP, giving up")); @@ -1427,7 +1428,6 @@ CServer::acceptHTTPClients(void*) } // wait a bit before retrying - log((CLOG_DEBUG1 "bind HTTP failed; waiting to retry")); CThread::sleep(5.0); } } diff --git a/server/server.cpp b/server/server.cpp index 9fcaee93..14e1f696 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -77,114 +77,106 @@ static int realMain(CMutex* mutex) { - // s_serverLock should have mutex locked on entry + // caller should have mutex locked on entry - try { - // initialize threading library - CThread::init(); - - // make logging thread safe - CMutex logMutex; - s_logMutex = &logMutex; - CLog::setLock(&logLock); - - bool locked = true; + int result = kExitSuccess; + do { try { - // if configuration has no screens then add this system - // as the default - if (s_config.begin() == s_config.end()) { - s_config.addScreen(s_name); - } + // initialize threading library + CThread::init(); - // set the contact address, if provided, in the config. - // otherwise, if the config doesn't have an address, use - // the default. - if (s_synergyAddress.isValid()) { - s_config.setSynergyAddress(s_synergyAddress); - } - else if (!s_config.getSynergyAddress().isValid()) { - s_config.setSynergyAddress(CNetworkAddress(kDefaultPort)); - } + // make logging thread safe + CMutex logMutex; + s_logMutex = &logMutex; + CLog::setLock(&logLock); - // set HTTP address is provided - if (s_httpAddress.isValid()) { - s_config.setHTTPAddress(s_httpAddress); - } + bool opened = false; + bool locked = true; + try { + // if configuration has no screens then add this system + // as the default + if (s_config.begin() == s_config.end()) { + s_config.addScreen(s_name); + } - // create server - s_server = new CServer(s_name); - s_server->setConfig(s_config); - if (!s_server->open()) { + // set the contact address, if provided, in the config. + // otherwise, if the config doesn't have an address, use + // the default. + if (s_synergyAddress.isValid()) { + s_config.setSynergyAddress(s_synergyAddress); + } + else if (!s_config.getSynergyAddress().isValid()) { + s_config.setSynergyAddress(CNetworkAddress(kDefaultPort)); + } + + // set HTTP address if provided + if (s_httpAddress.isValid()) { + s_config.setHTTPAddress(s_httpAddress); + } + + // create server + s_server = new CServer(s_name); + s_server->setConfig(s_config); + if (s_server->open()) { + opened = true; + + // run server (unlocked) + if (mutex != NULL) { + mutex->unlock(); + } + locked = false; + s_server->run(); + locked = true; + if (mutex != NULL) { + mutex->lock(); + } + + // clean up + s_server->close(); + } + else { + // wait a few seconds before retrying + if (s_restartable) { + CThread::sleep(3.0); + } + else { + result = kExitFailed; + } + } + + // clean up delete s_server; s_server = NULL; - return 16; + CLog::setLock(NULL); + s_logMutex = NULL; } - - // run server (unlocked) - if (mutex != NULL) { - mutex->unlock(); + catch (...) { + // clean up + if (!locked && mutex != NULL) { + mutex->lock(); + } + if (s_server != NULL) { + if (opened) { + s_server->close(); + } + delete s_server; + s_server = NULL; + } + CLog::setLock(NULL); + s_logMutex = NULL; + throw; } - locked = false; - s_server->run(); - locked = true; - if (mutex != NULL) { - mutex->lock(); - } - - // clean up - s_server->close(); - delete s_server; - s_server = NULL; - CLog::setLock(NULL); - s_logMutex = NULL; } - catch (...) { - // clean up - if (!locked && mutex != NULL) { - mutex->lock(); - } - if (s_server != NULL) { - s_server->close(); - delete s_server; - s_server = NULL; - } - CLog::setLock(NULL); - s_logMutex = NULL; - throw; + catch (XBase& e) { + log((CLOG_CRIT "failed: %s", e.what())); } - } - catch (XBase& e) { - log((CLOG_CRIT "failed: %s", e.what())); - return 16; - } - catch (XThread&) { - // terminated - return 1; - } + catch (XThread&) { + // terminated + return kExitTerminated; + } + } while (s_restartable); - return 0; -} - -static -int -restartMain() -{ - return realMain(NULL); -} - -// invoke realMain and wait for it. if s_restartable then keep -// restarting realMain until it returns a terminate code. -static -int -restartableMain() -{ - if (s_restartable) { - CPlatform platform; - return platform.restart(restartMain, 16); - } - else { - return realMain(NULL); - } + return result; } @@ -308,7 +300,7 @@ isArg(int argi, int argc, const char** argv, if (argi + minRequiredParameters >= argc) { log((CLOG_PRINT "%s: missing arguments for `%s'" BYE, pname, argv[argi], pname)); - bye(2); + bye(kExitArgs); } return true; } @@ -347,7 +339,7 @@ parse(int argc, const char** argv) catch (XSocketAddress&) { log((CLOG_PRINT "%s: invalid address for `%s'" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } ++i; } @@ -360,7 +352,7 @@ parse(int argc, const char** argv) catch (XSocketAddress&) { log((CLOG_PRINT "%s: invalid address for `%s'" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } ++i; } @@ -397,12 +389,12 @@ parse(int argc, const char** argv) else if (isArg(i, argc, argv, "-h", "--help")) { help(); - bye(0); + bye(kExitSuccess); } else if (isArg(i, argc, argv, NULL, "--version")) { version(); - bye(0); + bye(kExitSuccess); } #if WINDOWS_LIKE @@ -412,7 +404,7 @@ parse(int argc, const char** argv) log((CLOG_PRINT "%s: `--install' and `--uninstall'" " are mutually exclusive" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } } #endif @@ -424,7 +416,7 @@ parse(int argc, const char** argv) log((CLOG_PRINT "%s: `--install' and `--uninstall'" " are mutually exclusive" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } } #endif @@ -438,7 +430,7 @@ parse(int argc, const char** argv) else if (argv[i][0] == '-') { log((CLOG_PRINT "%s: unrecognized option `%s'" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } else { @@ -451,7 +443,7 @@ parse(int argc, const char** argv) if (i != argc) { log((CLOG_PRINT "%s: unrecognized option `%s'" BYE, pname, argv[i], pname)); - bye(2); + bye(kExitArgs); } // increase default filter level for daemon. the user must @@ -474,7 +466,7 @@ parse(int argc, const char** argv) if (!CLog::setFilter(s_logFilter)) { log((CLOG_PRINT "%s: unrecognized log level `%s'" BYE, pname, s_logFilter, pname)); - bye(2); + bye(kExitArgs); } } @@ -499,7 +491,7 @@ loadConfig(const char* pathname, bool require) if (require) { log((CLOG_PRINT "%s: cannot read configuration '%s': %s", pname, pathname, e.what())); - bye(3); + bye(kExitConfig); } else { log((CLOG_DEBUG "cannot read configuration \"%s\": %s", @@ -595,7 +587,7 @@ daemonStartup(IPlatform* iplatform, int argc, const char** argv) parse(argc, argv); if (s_install || s_uninstall) { // not allowed to install/uninstall from service - throw CWin32Platform::CDaemonFailed(1); + throw CWin32Platform::CDaemonFailed(kExitArgs); } // load configuration @@ -609,7 +601,7 @@ static int daemonStartup95(IPlatform*, int, const char**) { - return restartableMain(); + return realMain(NULL); } int WINAPI @@ -639,7 +631,7 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) int result = platform.daemonize(DAEMON_NAME, &daemonStartup); if (result == -1) { log((CLOG_CRIT "failed to start as a service" BYE, pname)); - return 16; + return kExitFailed; } return result; } @@ -654,7 +646,7 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) if (GetModuleFileName(NULL, path, sizeof(path) / sizeof(path[0])) == 0) { log((CLOG_CRIT "cannot determine absolute path to program")); - return 16; + return kExitFailed; } // construct the command line to start the service with @@ -681,24 +673,24 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) "Shares this system's mouse and keyboard with others.", path, commandLine.c_str())) { log((CLOG_CRIT "failed to install service")); - return 16; + return kExitFailed; } log((CLOG_PRINT "installed successfully")); - return 0; + return kExitSuccess; } else if (s_uninstall) { switch (platform.uninstallDaemon(DAEMON_NAME)) { case IPlatform::kSuccess: log((CLOG_PRINT "uninstalled successfully")); - return 0; + return kExitSuccess; case IPlatform::kFailed: log((CLOG_CRIT "failed to uninstall service")); - return 16; + return kExitFailed; case IPlatform::kAlready: log((CLOG_CRIT "service isn't installed")); - return 16; + return kExitFailed; } } @@ -716,18 +708,18 @@ WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) result = platform.daemonize(DAEMON_NAME, &daemonStartup95); if (result == -1) { log((CLOG_CRIT "failed to start as a service" BYE, pname)); - return 16; + return kExitFailed; } } else { // cannot start a service from the command line so just // run normally (except with log messages redirected). - result = restartableMain(); + result = realMain(NULL); } } else { // run - result = restartableMain(); + result = realMain(NULL); } CNetwork::cleanup(); @@ -741,7 +733,7 @@ static int daemonStartup(IPlatform*, int, const char**) { - return restartableMain(); + return realMain(NULL); } int @@ -767,11 +759,11 @@ main(int argc, char** argv) result = platform.daemonize(DAEMON_NAME, &daemonStartup); if (result == -1) { log((CLOG_CRIT "failed to daemonize")); - return 16; + return kExitFailed; } } else { - result = restartableMain(); + result = realMain(NULL); } CNetwork::cleanup(); diff --git a/synergy/ProtocolTypes.h b/synergy/ProtocolTypes.h index 391c8ea3..c4d48ae4 100644 --- a/synergy/ProtocolTypes.h +++ b/synergy/ProtocolTypes.h @@ -5,7 +5,7 @@ // version number static const SInt16 kProtocolMajorVersion = 0; -static const SInt16 kProtocolMinorVersion = 1; +static const SInt16 kProtocolMinorVersion = 7; // contact port number static const UInt16 kDefaultPort = 24800; @@ -87,7 +87,7 @@ static const char kMsgCScreenSaver[] = "CSEC%1i"; // sent by primary in response to a secondary screen's kMsgDInfo. // this is sent for every kMsgDInfo, whether or not the primary // had sent a kMsgQInfo. -static const char kMsgCInfoAck[] = "CIAK"; +static const char kMsgCInfoAck[] = "CIAK"; // @@ -165,16 +165,16 @@ static const char kMsgQInfo[] = "QINF"; static const char kMsgEIncompatible[] = "EICV%2i%2i"; // name provided when connecting is already in use: primary -> secondary -static const char kMsgEBusy[] = "EBSY"; +static const char kMsgEBusy[] = "EBSY"; // unknown client: primary -> secondary // name provided when connecting is not in primary's screen // configuration map. -static const char kMsgEUnknown[] = "EUNK"; +static const char kMsgEUnknown[] = "EUNK"; // protocol violation: primary -> secondary // primary should disconnect after sending this message. -static const char kMsgEBad[] = "EBAD"; +static const char kMsgEBad[] = "EBAD"; // diff --git a/synergy/Version.h b/synergy/Version.h index 24367162..5b8ae1c7 100644 --- a/synergy/Version.h +++ b/synergy/Version.h @@ -4,10 +4,19 @@ #include "BasicTypes.h" static const char* kCopyright = "Copyright (C) 2002 Chris Schoeneman"; +static const char* kContact = "Chris Schoeneman crs23@bigfoot.com"; -// build version +// build version. follows linux kernel style: minor number even implies +// a release version, odd implies development version. static const SInt16 kMajorVersion = 0; -static const SInt16 kMinorVersion = 5; -static const SInt16 kReleaseVersion = 0; +static const SInt16 kMinorVersion = 9; +static const SInt16 kReleaseVersion = 7; + +// exit codes +static const int kExitSuccess = 0; // successful completion +static const int kExitFailed = 1; // general failure +static const int kExitTerminated = 2; // killed by signal +static const int kExitArgs = 3; // bad arguments +static const int kExitConfig = 4; // cannot read configuration #endif