removed restart function from platform. no longer trying to
restart if the X server connection was lost; since synergy is likely to be started by xdm or the user's xsession, it's better for synergy to simply terminate when the connection is lost. synergy will still restart due to other errors. also fixed numerous other minor bugs and cleaned some stuff up (like app error codes are now consistent and enumerated in Version.h, for lack of a better place). and boosted version and protocol numbers.
This commit is contained in:
parent
d9ec880291
commit
c6ecc79c0d
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<char*>(&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!
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -7,22 +7,6 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <signal.h>
|
||||
#if HAVE_SYS_WAIT_H
|
||||
# include <sys/wait.h>
|
||||
#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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -34,6 +34,7 @@ CPrimaryClient::CPrimaryClient(IServer* server,
|
|||
|
||||
CPrimaryClient::~CPrimaryClient()
|
||||
{
|
||||
log((CLOG_DEBUG1 "destroying primary screen"));
|
||||
delete m_screen;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue