aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/thread.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-11-15 11:30:56 +0100
committerGitHub <[email protected]>2023-11-15 11:30:56 +0100
commitd02b0720813a62a4f1fe875e6e784843f5c2da46 (patch)
tree31768a0f52793b0205f156c0b827f11decc2c479 /src/zencore/thread.cpp
parentadd host name to sentry (#537) (diff)
downloadzen-d02b0720813a62a4f1fe875e6e784843f5c2da46.tar.xz
zen-d02b0720813a62a4f1fe875e6e784843f5c2da46.zip
fix race contdition when signaling shutdown of process and waiting for completion (#539)
Diffstat (limited to 'src/zencore/thread.cpp')
-rw-r--r--src/zencore/thread.cpp56
1 files changed, 48 insertions, 8 deletions
diff --git a/src/zencore/thread.cpp b/src/zencore/thread.cpp
index 1f1b1b8f5..99d7cdc61 100644
--- a/src/zencore/thread.cpp
+++ b/src/zencore/thread.cpp
@@ -606,7 +606,7 @@ ProcessHandle::Terminate(int ExitCode)
bSuccess = (WaitResult != WAIT_OBJECT_0);
#elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
ZEN_UNUSED(ExitCode);
- bSuccess = (kill(m_Pid, SIGKILL) == 0);
+ bSuccess = (kill(m_Pid, SIGKILL) == 0);
#endif
if (!bSuccess)
@@ -650,25 +650,65 @@ ProcessHandle::Wait(int TimeoutMs)
break;
}
#elif ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
+ if (TimeoutMs < 0)
+ {
+ int WaitState = 0;
+ int Res = waitpid(m_Pid, &WaitState, WCONTINUED | WUNTRACED);
+ if (Res == -1)
+ {
+ int32_t LastError = zen::GetLastError();
+ if (LastError == ECHILD || LastError == ESRCH)
+ {
+ return true;
+ }
+ ThrowSystemError(static_cast<uint32_t>(LastError), "Process::Wait waitpid failed"sv);
+ }
+ if (WIFEXITED(WaitState))
+ {
+ return true;
+ }
+ if (WIFSIGNALED(WaitState))
+ {
+ return true;
+ }
+ return false;
+ }
+
const int SleepMs = 20;
timespec SleepTime = {0, SleepMs * 1000 * 1000};
- for (int i = 0;; i += SleepMs)
+ for (int SleepedTimeMS = 0;; SleepedTimeMS += SleepMs)
{
-# if ZEN_PLATFORM_MAC
int WaitState = 0;
- waitpid(m_Pid, &WaitState, WNOHANG | WCONTINUED | WUNTRACED);
-# endif
+ int Res = waitpid(m_Pid, &WaitState, WNOHANG | WCONTINUED | WUNTRACED);
+ if (Res == -1)
+ {
+ int32_t LastError = zen::GetLastError();
+ if (LastError == ECHILD || LastError == ESRCH)
+ {
+ return true;
+ }
+ ThrowSystemError(static_cast<uint32_t>(LastError), "Process::Wait waitpid failed"sv);
+ }
+ if (WIFEXITED(WaitState))
+ {
+ return true;
+ }
+ if (WIFSIGNALED(WaitState))
+ {
+ return true;
+ }
if (kill(m_Pid, 0) < 0)
{
- if (zen::GetLastError() == ESRCH)
+ int32_t LastError = zen::GetLastError();
+ if (LastError == ECHILD || LastError == ESRCH)
{
return true;
}
- break;
+ ThrowSystemError(static_cast<uint32_t>(LastError), "Process::Wait kill failed"sv);
}
- if (TimeoutMs >= 0 && i >= TimeoutMs)
+ if (SleepedTimeMS >= TimeoutMs)
{
return false;
}