lib/arch/win32: Use standard mutex primitives in daemon code

This commit is contained in:
Povilas Kanapickas 2021-11-03 02:58:41 +02:00
parent c59074835f
commit 959306fb1b
2 changed files with 18 additions and 39 deletions

View File

@ -320,7 +320,6 @@ int
ArchDaemonWindows::doRunDaemon(RunFunc run) ArchDaemonWindows::doRunDaemon(RunFunc run)
{ {
// should only be called from DaemonFunc // should only be called from DaemonFunc
assert(m_serviceMutex != NULL);
assert(run != NULL); assert(run != NULL);
// create message queue for this thread // create message queue for this thread
@ -328,32 +327,30 @@ ArchDaemonWindows::doRunDaemon(RunFunc run)
PeekMessage(&dummy, NULL, 0, 0, PM_NOREMOVE); PeekMessage(&dummy, NULL, 0, 0, PM_NOREMOVE);
int result = 0; int result = 0;
ARCH->lockMutex(m_serviceMutex); std::unique_lock<std::mutex> lock(service_mutex_);
m_daemonThreadID = GetCurrentThreadId(); m_daemonThreadID = GetCurrentThreadId();
while (m_serviceState != SERVICE_STOPPED) { while (m_serviceState != SERVICE_STOPPED) {
// wait until we're told to start // wait until we're told to start
while (!isRunState(m_serviceState) && while (!isRunState(m_serviceState) &&
m_serviceState != SERVICE_STOP_PENDING) { m_serviceState != SERVICE_STOP_PENDING) {
ArchMutexLock lock{m_serviceMutex, std::adopt_lock}; ARCH->wait_cond_var(service_cv_, lock, -1.0);
ARCH->waitCondVar(m_serviceCondVar, lock, -1.0);
} }
// run unless told to stop // run unless told to stop
if (m_serviceState != SERVICE_STOP_PENDING) { if (m_serviceState != SERVICE_STOP_PENDING) {
ARCH->unlockMutex(m_serviceMutex); lock.unlock();
try { try {
result = run(); result = run();
} }
catch (...) { catch (...) {
ARCH->lockMutex(m_serviceMutex); lock.lock();
setStatusError(0); setStatusError(0);
m_serviceState = SERVICE_STOPPED; m_serviceState = SERVICE_STOPPED;
setStatus(m_serviceState); setStatus(m_serviceState);
ARCH->broadcastCondVar(m_serviceCondVar); service_cv_.notify_all();
ARCH->unlockMutex(m_serviceMutex);
throw; throw;
} }
ARCH->lockMutex(m_serviceMutex); lock.lock();
} }
// notify of new state // notify of new state
@ -364,22 +361,20 @@ ArchDaemonWindows::doRunDaemon(RunFunc run)
m_serviceState = SERVICE_STOPPED; m_serviceState = SERVICE_STOPPED;
} }
setStatus(m_serviceState); setStatus(m_serviceState);
ARCH->broadcastCondVar(m_serviceCondVar); service_cv_.notify_all();
} }
ARCH->unlockMutex(m_serviceMutex);
return result; return result;
} }
void void
ArchDaemonWindows::doDaemonRunning(bool running) ArchDaemonWindows::doDaemonRunning(bool running)
{ {
ARCH->lockMutex(m_serviceMutex); std::lock_guard<std::mutex> lock(service_mutex_);
if (running) { if (running) {
m_serviceState = SERVICE_RUNNING; m_serviceState = SERVICE_RUNNING;
setStatus(m_serviceState); setStatus(m_serviceState);
ARCH->broadcastCondVar(m_serviceCondVar); service_cv_.notify_all();
} }
ARCH->unlockMutex(m_serviceMutex);
} }
UINT UINT
@ -439,18 +434,12 @@ ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn)
typedef std::vector<std::string> Arguments; typedef std::vector<std::string> Arguments;
const char** argv = const_cast<const char**>(argvIn); const char** argv = const_cast<const char**>(argvIn);
// create synchronization objects
m_serviceMutex = ARCH->newMutex();
m_serviceCondVar = ARCH->newCondVar();
// register our service handler function // register our service handler function
m_statusHandle = RegisterServiceCtrlHandler(argv[0], m_statusHandle = RegisterServiceCtrlHandler(argv[0],
&ArchDaemonWindows::serviceHandlerEntry); &ArchDaemonWindows::serviceHandlerEntry);
if (m_statusHandle == 0) { if (m_statusHandle == 0) {
// cannot start as service // cannot start as service
m_daemonResult = -1; m_daemonResult = -1;
ARCH->closeCondVar(m_serviceCondVar);
ARCH->closeMutex(m_serviceMutex);
return; return;
} }
@ -544,10 +533,6 @@ ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn)
m_daemonResult = -1; m_daemonResult = -1;
} }
// clean up
ARCH->closeCondVar(m_serviceCondVar);
ARCH->closeMutex(m_serviceMutex);
// we're going to exit now, so set status to stopped // we're going to exit now, so set status to stopped
m_serviceState = SERVICE_STOPPED; m_serviceState = SERVICE_STOPPED;
setStatus(m_serviceState, 0, 10000); setStatus(m_serviceState, 0, 10000);
@ -562,17 +547,13 @@ ArchDaemonWindows::serviceMainEntry(DWORD argc, LPTSTR* argv)
void void
ArchDaemonWindows::serviceHandler(DWORD ctrl) ArchDaemonWindows::serviceHandler(DWORD ctrl)
{ {
assert(m_serviceMutex != NULL); std::unique_lock<std::mutex> lock(service_mutex_);
assert(m_serviceCondVar != NULL);
ARCH->lockMutex(m_serviceMutex);
// ignore request if service is already stopped // ignore request if service is already stopped
if (s_daemon == NULL || m_serviceState == SERVICE_STOPPED) { if (s_daemon == NULL || m_serviceState == SERVICE_STOPPED) {
if (s_daemon != NULL) { if (s_daemon != NULL) {
setStatus(m_serviceState); setStatus(m_serviceState);
} }
ARCH->unlockMutex(m_serviceMutex);
return; return;
} }
@ -582,8 +563,7 @@ ArchDaemonWindows::serviceHandler(DWORD ctrl)
setStatus(m_serviceState, 0, 5000); setStatus(m_serviceState, 0, 5000);
PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0); PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0);
while (isRunState(m_serviceState)) { while (isRunState(m_serviceState)) {
ArchMutexLock lock{m_serviceMutex, std::adopt_lock}; ARCH->wait_cond_var(service_cv_, lock, -1.0);
ARCH->waitCondVar(m_serviceCondVar, lock, -1.0);
} }
break; break;
@ -591,7 +571,7 @@ ArchDaemonWindows::serviceHandler(DWORD ctrl)
// FIXME -- maybe should flush quit messages from queue // FIXME -- maybe should flush quit messages from queue
m_serviceState = SERVICE_CONTINUE_PENDING; m_serviceState = SERVICE_CONTINUE_PENDING;
setStatus(m_serviceState, 0, 5000); setStatus(m_serviceState, 0, 5000);
ARCH->broadcastCondVar(m_serviceCondVar); service_cv_.notify_all();
break; break;
case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_STOP:
@ -599,10 +579,9 @@ ArchDaemonWindows::serviceHandler(DWORD ctrl)
m_serviceState = SERVICE_STOP_PENDING; m_serviceState = SERVICE_STOP_PENDING;
setStatus(m_serviceState, 0, 5000); setStatus(m_serviceState, 0, 5000);
PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0); PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0);
ARCH->broadcastCondVar(m_serviceCondVar); service_cv_.notify_all();
while (isRunState(m_serviceState)) { while (isRunState(m_serviceState)) {
ArchMutexLock lock{m_serviceMutex, std::adopt_lock}; ARCH->wait_cond_var(service_cv_, lock, -1.0);
ARCH->waitCondVar(m_serviceCondVar, lock, -1.0);
} }
break; break;
@ -614,8 +593,6 @@ ArchDaemonWindows::serviceHandler(DWORD ctrl)
setStatus(m_serviceState); setStatus(m_serviceState);
break; break;
} }
ARCH->unlockMutex(m_serviceMutex);
} }
void WINAPI void WINAPI

View File

@ -26,6 +26,8 @@
#include <Windows.h> #include <Windows.h>
#include <tchar.h> #include <tchar.h>
#include <condition_variable>
#define ARCH_DAEMON ArchDaemonWindows #define ARCH_DAEMON ArchDaemonWindows
//! Win32 implementation of IArchDaemon //! Win32 implementation of IArchDaemon
@ -122,8 +124,8 @@ private:
private: private:
static ArchDaemonWindows* s_daemon; static ArchDaemonWindows* s_daemon;
ArchMutex m_serviceMutex; std::mutex service_mutex_;
ArchCond m_serviceCondVar; std::condition_variable service_cv_;
DWORD m_serviceState; DWORD m_serviceState;
bool m_serviceHandlerWaiting; bool m_serviceHandlerWaiting;
bool m_serviceRunning; bool m_serviceRunning;