From 4b1b3edc21acf3b19649a85e49a57464bf169314 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Thu, 16 Sep 2021 21:04:35 +0200 Subject: Added ProcessMonitor class, which is used to monitor a number of sponsor processes, to control Zen instance lifetime --- zencore/thread.cpp | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'zencore/thread.cpp') diff --git a/zencore/thread.cpp b/zencore/thread.cpp index 598466bb4..ee00d38d4 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -76,6 +76,13 @@ Event::Reset() ResetEvent(m_EventHandle); } +void +Event::Close() +{ + CloseHandle(m_EventHandle); + m_EventHandle = nullptr; +} + bool Event::Wait(int TimeoutMs) { @@ -168,6 +175,7 @@ ProcessHandle::Initialize(void* ProcessHandle) ZEN_ASSERT(m_ProcessHandle == nullptr); // TODO: perform some debug verification here to verify it's a valid handle? m_ProcessHandle = ProcessHandle; + m_Pid = GetProcessId(m_ProcessHandle); } ProcessHandle::~ProcessHandle() @@ -255,6 +263,73 @@ ProcessHandle::Wait(int TimeoutMs) return false; } +////////////////////////////////////////////////////////////////////////// + +ProcessMonitor::ProcessMonitor() +{ +} + +ProcessMonitor::~ProcessMonitor() +{ + RwLock::ExclusiveLockScope _(m_Lock); + + for (HANDLE& Proc : m_ProcessHandles) + { + CloseHandle(Proc); + Proc = 0; + } +} + +bool +ProcessMonitor::IsRunning() +{ + RwLock::ExclusiveLockScope _(m_Lock); + + bool FoundOne = false; + + for (HANDLE& Proc : m_ProcessHandles) + { + DWORD ExitCode = 0; + GetExitCodeProcess(Proc, &ExitCode); + + if (ExitCode != STILL_ACTIVE) + { + CloseHandle(Proc); + Proc = 0; + } + else + { + // Still alive + FoundOne = true; + } + } + + std::erase_if(m_ProcessHandles, [](HANDLE Handle) { return Handle == 0; }); + + return FoundOne; +} + +void +ProcessMonitor::AddPid(int Pid) +{ + HANDLE ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, Pid); + + if (ProcessHandle) + { + RwLock::ExclusiveLockScope _(m_Lock); + m_ProcessHandles.push_back(ProcessHandle); + } +} + +bool +ProcessMonitor::IsActive() const +{ + RwLock::SharedLockScope _(m_Lock); + return m_ProcessHandles.empty() == false; +} + +////////////////////////////////////////////////////////////////////////// + bool IsProcessRunning(int pid) { -- cgit v1.2.3 From 14a9b3d70c39e9823bdd93b44c5bc7479062defd Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Thu, 16 Sep 2021 22:49:59 +0200 Subject: clang-format --- zencore/thread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'zencore/thread.cpp') diff --git a/zencore/thread.cpp b/zencore/thread.cpp index ee00d38d4..1c7e4b3ab 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -76,7 +76,7 @@ Event::Reset() ResetEvent(m_EventHandle); } -void +void Event::Close() { CloseHandle(m_EventHandle); @@ -291,7 +291,7 @@ ProcessMonitor::IsRunning() { DWORD ExitCode = 0; GetExitCodeProcess(Proc, &ExitCode); - + if (ExitCode != STILL_ACTIVE) { CloseHandle(Proc); -- cgit v1.2.3 From 025999f216f0fe99d0eacd1f7a9c6276b834bcb8 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 17 Sep 2021 19:04:26 +0200 Subject: Removed WindowsException from public headers --- zencore/thread.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'zencore/thread.cpp') diff --git a/zencore/thread.cpp b/zencore/thread.cpp index 1c7e4b3ab..c02bf508a 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -257,7 +257,8 @@ ProcessHandle::Wait(int TimeoutMs) case WAIT_FAILED: // What might go wrong here, and what is meaningful to act on? - throw WindowsException("Process::Wait failed"); + using namespace std::literals; + ThrowLastError("Process::Wait failed"sv); } return false; -- cgit v1.2.3 From 28de689b30b64c0c2691b05866c27c84e0a21ff3 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Fri, 17 Sep 2021 23:15:56 +0200 Subject: IsProcessRunning now throws if it fails the function fails to get a handle to the process due to an error (unless it is because the process does not exist) --- zencore/thread.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'zencore/thread.cpp') diff --git a/zencore/thread.cpp b/zencore/thread.cpp index c02bf508a..c92cca6de 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -334,16 +334,32 @@ ProcessMonitor::IsActive() const bool IsProcessRunning(int pid) { + // This function is arguably not super useful, a pid can be re-used + // by the OS so holding on to a pid and polling it over some time + // period will not necessarily tell you what you probably want to know. + +#if ZEN_PLATFORM_WINDOWS HANDLE hProc = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); - if (hProc == NULL) + if (!hProc) { - return false; + DWORD Error = zen::GetLastError(); + + if (Error == ERROR_INVALID_PARAMETER) + { + return false; + } + + using namespace fmt::literals; + ThrowSystemError(Error, "failed to open process with pid {}"_format(pid)); } CloseHandle(hProc); return true; +#else + ZEN_NOT_IMPLEMENTED(); +#endif } int -- cgit v1.2.3 From c86315ea955408659eb7ea32798693975e27b9b7 Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Sun, 19 Sep 2021 22:35:12 +0200 Subject: Changed so Windows also uses the portable std::mutex implementation and reworked some code which would not compile after the change --- zencore/thread.cpp | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'zencore/thread.cpp') diff --git a/zencore/thread.cpp b/zencore/thread.cpp index c92cca6de..d4f101454 100644 --- a/zencore/thread.cpp +++ b/zencore/thread.cpp @@ -17,41 +17,25 @@ namespace zen { void RwLock::AcquireShared() { -#if ZEN_PLATFORM_WINDOWS - AcquireSRWLockShared((PSRWLOCK)&m_Srw); -#else m_Mutex.lock_shared(); -#endif } void RwLock::ReleaseShared() { -#if ZEN_PLATFORM_WINDOWS - ReleaseSRWLockShared((PSRWLOCK)&m_Srw); -#else m_Mutex.unlock_shared(); -#endif } void RwLock::AcquireExclusive() { -#if ZEN_PLATFORM_WINDOWS - AcquireSRWLockExclusive((PSRWLOCK)&m_Srw); -#else m_Mutex.lock(); -#endif } void RwLock::ReleaseExclusive() { -#if ZEN_PLATFORM_WINDOWS - ReleaseSRWLockExclusive((PSRWLOCK)&m_Srw); -#else m_Mutex.unlock(); -#endif } Event::Event() -- cgit v1.2.3