diff options
| author | Dan Engelbrecht <[email protected]> | 2023-11-15 11:30:56 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-11-15 11:30:56 +0100 |
| commit | d02b0720813a62a4f1fe875e6e784843f5c2da46 (patch) | |
| tree | 31768a0f52793b0205f156c0b827f11decc2c479 /src | |
| parent | add host name to sentry (#537) (diff) | |
| download | zen-d02b0720813a62a4f1fe875e6e784843f5c2da46.tar.xz zen-d02b0720813a62a4f1fe875e6e784843f5c2da46.zip | |
fix race contdition when signaling shutdown of process and waiting for completion (#539)
Diffstat (limited to 'src')
| -rw-r--r-- | src/zencore/thread.cpp | 56 | ||||
| -rw-r--r-- | src/zenserver/main.cpp | 8 | ||||
| -rw-r--r-- | src/zenserver/zenserver.cpp | 2 | ||||
| -rw-r--r-- | src/zenutil/zenserverprocess.cpp | 10 |
4 files changed, 63 insertions, 13 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; } diff --git a/src/zenserver/main.cpp b/src/zenserver/main.cpp index 69cc2bbf5..44330d4c8 100644 --- a/src/zenserver/main.cpp +++ b/src/zenserver/main.cpp @@ -198,13 +198,15 @@ ZenEntryPoint::Run() ShutdownThread.reset(new std::thread{[&] { SetCurrentThreadName("shutdown_monitor"); - ZEN_INFO("shutdown monitor thread waiting for shutdown signal '{}'", ShutdownEventName); + ZEN_INFO("shutdown monitor thread waiting for shutdown signal '{}' for process {}", + ShutdownEventName, + zen::GetCurrentProcessId()); if (ShutdownEvent->Wait()) { if (!IsApplicationExitRequested()) { - ZEN_INFO("shutdown signal received"); + ZEN_INFO("shutdown signal for pid {} received", zen::GetCurrentProcessId()); Server.RequestExit(0); } } @@ -244,7 +246,7 @@ ZenEntryPoint::Run() } catch (std::exception& e) { - ZEN_CRITICAL("Caught exception in main: {}", e.what()); + ZEN_CRITICAL("Caught exception in main for process {}: {}", zen::GetCurrentProcessId(), e.what()); if (!IsApplicationExitRequested()) { RequestApplicationExit(1); diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp index 7111900ec..9d3502a23 100644 --- a/src/zenserver/zenserver.cpp +++ b/src/zenserver/zenserver.cpp @@ -720,7 +720,7 @@ ZenServer::CheckSigInt() { if (utils::SignalCounter[SIGINT] > 0) { - ZEN_INFO("SIGINT triggered (Ctrl+C), exiting"); + ZEN_INFO("SIGINT triggered (Ctrl+C) for process {}, exiting", zen::GetCurrentProcessId()); RequestExit(128 + SIGINT); return; } diff --git a/src/zenutil/zenserverprocess.cpp b/src/zenutil/zenserverprocess.cpp index 83c6668ba..00736321c 100644 --- a/src/zenutil/zenserverprocess.cpp +++ b/src/zenutil/zenserverprocess.cpp @@ -468,7 +468,14 @@ ZenServerInstance::ZenServerInstance(ZenServerEnvironment& TestEnvironment) : m_ ZenServerInstance::~ZenServerInstance() { - Shutdown(); + try + { + Shutdown(); + } + catch (const std::exception& Err) + { + ZEN_ERROR("Shutting down zenserver instance failed, reason: '{}'", Err.what()); + } } void @@ -491,6 +498,7 @@ ZenServerInstance::Shutdown() else { SignalShutdown(); + ZEN_DEBUG("Waiting for zenserver process {} to shut down", m_Process.Pid()); m_Process.Wait(); m_Process.Reset(); } |