mirror of
https://github.com/debauchee/barrier.git
synced 2026-05-08 23:14:20 +08:00
Merged Win32 updates. Added full warnings on g++. Fixed bug in
client when handling server rejection.
This commit is contained in:
@@ -24,10 +24,9 @@
|
||||
|
||||
CArchDaemonWindows* CArchDaemonWindows::s_daemon = NULL;
|
||||
|
||||
CArchDaemonWindows::CArchDaemonWindows() :
|
||||
m_daemonThread(NULL)
|
||||
CArchDaemonWindows::CArchDaemonWindows()
|
||||
{
|
||||
// do nothing
|
||||
m_quitMessage = RegisterWindowMessage("SynergyDaemonExit");
|
||||
}
|
||||
|
||||
CArchDaemonWindows::~CArchDaemonWindows()
|
||||
@@ -55,6 +54,17 @@ CArchDaemonWindows::daemonRunning(bool running)
|
||||
}
|
||||
}
|
||||
|
||||
UINT
|
||||
CArchDaemonWindows::getDaemonQuitMessage()
|
||||
{
|
||||
if (s_daemon != NULL) {
|
||||
return s_daemon->doGetDaemonQuitMessage();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CArchDaemonWindows::daemonFailed(int result)
|
||||
{
|
||||
@@ -437,122 +447,89 @@ CArchDaemonWindows::openUserStartupKey()
|
||||
return CArchMiscWindows::openKey(HKEY_CURRENT_USER, s_keyNames);
|
||||
}
|
||||
|
||||
bool
|
||||
CArchDaemonWindows::isRunState(DWORD state)
|
||||
{
|
||||
switch (state) {
|
||||
case SERVICE_START_PENDING:
|
||||
case SERVICE_CONTINUE_PENDING:
|
||||
case SERVICE_RUNNING:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
CArchDaemonWindows::doRunDaemon(RunFunc run)
|
||||
{
|
||||
// should only be called from DaemonFunc
|
||||
assert(m_serviceMutex != NULL);
|
||||
assert(run != NULL);
|
||||
assert(run != NULL);
|
||||
|
||||
// create message queue for this thread
|
||||
MSG dummy;
|
||||
PeekMessage(&dummy, NULL, 0, 0, PM_NOREMOVE);
|
||||
|
||||
int result = 0;
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
try {
|
||||
int result;
|
||||
m_serviceHandlerWaiting = false;
|
||||
m_serviceRunning = false;
|
||||
for (;;) {
|
||||
// mark server as running
|
||||
setStatus(SERVICE_RUNNING);
|
||||
|
||||
// run callback in another thread
|
||||
m_serviceRunning = true;
|
||||
m_daemonThread = ARCH->newThread(
|
||||
&CArchDaemonWindows::runDaemonThreadEntry, run);
|
||||
ARCH->wait(m_daemonThread, -1.0);
|
||||
result = reinterpret_cast<int>(
|
||||
ARCH->getResultOfThread(m_daemonThread));
|
||||
m_serviceRunning = false;
|
||||
|
||||
// notify handler that the server stopped. if handler
|
||||
// isn't waiting then we stopped unexpectedly and we
|
||||
// quit.
|
||||
if (m_serviceHandlerWaiting) {
|
||||
m_serviceHandlerWaiting = false;
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
// wait until we're told what to do next
|
||||
while (m_serviceState != SERVICE_RUNNING &&
|
||||
m_serviceState != SERVICE_STOPPED) {
|
||||
ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0);
|
||||
}
|
||||
|
||||
// exit loop if we've been told to stop
|
||||
if (m_serviceState == SERVICE_STOPPED) {
|
||||
break;
|
||||
}
|
||||
|
||||
// done with callback thread
|
||||
ARCH->closeThread(m_daemonThread);
|
||||
m_daemonThread = NULL;
|
||||
}
|
||||
|
||||
// prevent daemonHandler from changing state
|
||||
m_serviceState = SERVICE_STOPPED;
|
||||
|
||||
// tell service control that the service is stopped.
|
||||
// FIXME -- hopefully this will ensure that our handler won't
|
||||
// be called again but i can't find documentation that
|
||||
// verifies that. if it does it'll crash on the mutex that
|
||||
// we're about to destroy.
|
||||
setStatus(m_serviceState);
|
||||
|
||||
// clean up
|
||||
if (m_daemonThread != NULL) {
|
||||
ARCH->closeThread(m_daemonThread);
|
||||
m_daemonThread = NULL;
|
||||
}
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (...) {
|
||||
// FIXME -- report error
|
||||
|
||||
// prevent serviceHandler from changing state
|
||||
m_serviceState = SERVICE_STOPPED;
|
||||
|
||||
// set status
|
||||
setStatusError(0);
|
||||
|
||||
// wake up serviceHandler if it's waiting then wait for it
|
||||
if (m_serviceHandlerWaiting) {
|
||||
m_serviceHandlerWaiting = false;
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
m_daemonThreadID = GetCurrentThreadId();
|
||||
while (m_serviceState != SERVICE_STOPPED) {
|
||||
// wait until we're told to start
|
||||
while (!isRunState(m_serviceState) &&
|
||||
m_serviceState != SERVICE_STOP_PENDING) {
|
||||
ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0);
|
||||
// serviceHandler has exited by now
|
||||
}
|
||||
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
throw;
|
||||
// run unless told to stop
|
||||
if (m_serviceState != SERVICE_STOP_PENDING) {
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
try {
|
||||
result = run();
|
||||
}
|
||||
catch (...) {
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
setStatusError(0);
|
||||
m_serviceState = SERVICE_STOPPED;
|
||||
setStatus(m_serviceState);
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
throw;
|
||||
}
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
}
|
||||
|
||||
// notify of new state
|
||||
if (m_serviceState == SERVICE_PAUSE_PENDING) {
|
||||
m_serviceState = SERVICE_PAUSED;
|
||||
}
|
||||
else {
|
||||
m_serviceState = SERVICE_STOPPED;
|
||||
}
|
||||
setStatus(m_serviceState);
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
}
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
CArchDaemonWindows::doDaemonRunning(bool running)
|
||||
{
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
if (running) {
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
}
|
||||
else {
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
m_serviceState = SERVICE_RUNNING;
|
||||
setStatus(m_serviceState);
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
}
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
}
|
||||
|
||||
void*
|
||||
CArchDaemonWindows::runDaemonThread(RunFunc run)
|
||||
UINT
|
||||
CArchDaemonWindows::doGetDaemonQuitMessage()
|
||||
{
|
||||
return reinterpret_cast<void*>(run());
|
||||
}
|
||||
|
||||
void*
|
||||
CArchDaemonWindows::runDaemonThreadEntry(void* vrun)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
|
||||
return s_daemon->runDaemonThread(reinterpret_cast<RunFunc>(vrun));
|
||||
return m_quitMessage;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -583,6 +560,8 @@ CArchDaemonWindows::setStatus(DWORD state, DWORD step, DWORD waitHint)
|
||||
void
|
||||
CArchDaemonWindows::setStatusError(DWORD error)
|
||||
{
|
||||
assert(s_daemon != NULL);
|
||||
|
||||
SERVICE_STATUS status;
|
||||
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS |
|
||||
SERVICE_INTERACTIVE_PROCESS;
|
||||
@@ -605,11 +584,10 @@ CArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn)
|
||||
const char** argv = const_cast<const char**>(argvIn);
|
||||
|
||||
// create synchronization objects
|
||||
m_serviceMutex = ARCH->newMutex();
|
||||
m_serviceCondVar = ARCH->newCondVar();
|
||||
m_serviceState = SERVICE_RUNNING;
|
||||
|
||||
// register our service handler functiom
|
||||
m_serviceMutex = ARCH->newMutex();
|
||||
m_serviceCondVar = ARCH->newCondVar();
|
||||
|
||||
// register our service handler function
|
||||
m_statusHandle = RegisterServiceCtrlHandler(argv[0],
|
||||
&CArchDaemonWindows::serviceHandlerEntry);
|
||||
if (m_statusHandle == NULL) {
|
||||
@@ -621,7 +599,8 @@ CArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn)
|
||||
}
|
||||
|
||||
// tell service control manager that we're starting
|
||||
setStatus(SERVICE_START_PENDING, 0, 10000);
|
||||
m_serviceState = SERVICE_START_PENDING;
|
||||
setStatus(m_serviceState, 0, 10000);
|
||||
|
||||
// if no arguments supplied then try getting them from the registry.
|
||||
// the first argument doesn't count because it's the service name.
|
||||
@@ -726,58 +705,40 @@ CArchDaemonWindows::serviceHandler(DWORD ctrl)
|
||||
ARCH->lockMutex(m_serviceMutex);
|
||||
|
||||
// ignore request if service is already stopped
|
||||
if (m_serviceState == SERVICE_STOPPED) {
|
||||
setStatus(m_serviceState);
|
||||
if (s_daemon == NULL || m_serviceState == SERVICE_STOPPED) {
|
||||
if (s_daemon != NULL) {
|
||||
setStatus(m_serviceState);
|
||||
}
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ctrl) {
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
// update state
|
||||
m_serviceState = SERVICE_PAUSE_PENDING;
|
||||
setStatus(m_serviceState, 0, 5000);
|
||||
|
||||
// stop run callback if running and wait for it to finish
|
||||
if (m_serviceRunning) {
|
||||
m_serviceHandlerWaiting = true;
|
||||
ARCH->cancelThread(m_daemonThread);
|
||||
PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0);
|
||||
while (isRunState(m_serviceState)) {
|
||||
ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0);
|
||||
}
|
||||
|
||||
// update state if service hasn't stopped while we were waiting
|
||||
if (m_serviceState != SERVICE_STOPPED) {
|
||||
m_serviceState = SERVICE_PAUSED;
|
||||
}
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
// required status update
|
||||
setStatus(m_serviceState);
|
||||
|
||||
// update state but let main loop send RUNNING notification
|
||||
m_serviceState = SERVICE_RUNNING;
|
||||
// FIXME -- maybe should flush quit messages from queue
|
||||
m_serviceState = SERVICE_CONTINUE_PENDING;
|
||||
setStatus(m_serviceState, 0, 5000);
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
return;
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_STOP:
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
// update state
|
||||
m_serviceState = SERVICE_STOP_PENDING;
|
||||
setStatus(m_serviceState, 0, 5000);
|
||||
|
||||
// stop run callback if running and wait for it to finish
|
||||
if (m_serviceRunning) {
|
||||
m_serviceHandlerWaiting = true;
|
||||
ARCH->cancelThread(m_daemonThread);
|
||||
PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0);
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
while (isRunState(m_serviceState)) {
|
||||
ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0);
|
||||
}
|
||||
|
||||
// update state
|
||||
m_serviceState = SERVICE_STOPPED;
|
||||
ARCH->broadcastCondVar(m_serviceCondVar);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -785,12 +746,10 @@ CArchDaemonWindows::serviceHandler(DWORD ctrl)
|
||||
// fall through
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
setStatus(m_serviceState);
|
||||
break;
|
||||
}
|
||||
|
||||
// send update
|
||||
setStatus(m_serviceState);
|
||||
|
||||
ARCH->unlockMutex(m_serviceMutex);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user