aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/zenserverprocess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenutil/zenserverprocess.cpp')
-rw-r--r--src/zenutil/zenserverprocess.cpp152
1 files changed, 101 insertions, 51 deletions
diff --git a/src/zenutil/zenserverprocess.cpp b/src/zenutil/zenserverprocess.cpp
index 83c6668ba..909692fbc 100644
--- a/src/zenutil/zenserverprocess.cpp
+++ b/src/zenutil/zenserverprocess.cpp
@@ -12,6 +12,8 @@
#include <atomic>
+#include <gsl/gsl-lite.hpp>
+
#if ZEN_PLATFORM_WINDOWS
# include <zencore/windows.h>
#else
@@ -468,7 +470,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
@@ -480,19 +489,33 @@ ZenServerInstance::SignalShutdown()
void
ZenServerInstance::Shutdown()
{
- if (m_Process.IsValid() && m_ShutdownOnDestroy)
+ if (m_Process.IsValid())
{
- if (m_Terminate)
+ if (m_ShutdownOnDestroy)
{
- ZEN_INFO("Terminating zenserver process");
- m_Process.Terminate(111);
- m_Process.Reset();
+ if (m_Terminate)
+ {
+ ZEN_INFO("Terminating zenserver process {}", m_Name);
+ m_Process.Terminate(111);
+ m_Process.Reset();
+ ZEN_DEBUG("zenserver process {} ({}) terminated", m_Name, m_Process.Pid());
+ }
+ else
+ {
+ ZEN_DEBUG("Requesting zenserver process {} ({}) to shut down", m_Name, m_Process.Pid());
+ SignalShutdown();
+ ZEN_DEBUG("Waiting for zenserver process {} ({}) to shut down", m_Name, m_Process.Pid());
+ while (!m_Process.Wait(5000))
+ {
+ ZEN_WARN("Waiting for zenserver process {} ({}) timed out", m_Name, m_Process.Pid());
+ }
+ m_Process.Reset();
+ }
+ ZEN_DEBUG("zenserver process {} ({}) exited", m_Name, m_Process.Pid());
}
else
{
- SignalShutdown();
- m_Process.Wait();
- m_Process.Reset();
+ ZEN_DEBUG("Detached from zenserver process {} ({})", m_Name, m_Process.Pid());
}
}
}
@@ -509,10 +532,9 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
ChildEventName << "Zen_Child_" << ChildId;
NamedEvent ChildEvent{ChildEventName};
- CreateShutdownEvent(BasePort);
-
ExtendableStringBuilder<32> LogId;
LogId << "Zen" << ChildId;
+ m_Name = LogId.ToString();
ExtendableStringBuilder<512> CommandLine;
CommandLine << "zenserver" ZEN_EXE_SUFFIX_LITERAL; // see CreateProc() call for actual binary path
@@ -526,7 +548,8 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
m_OwnerPid = MyPid;
}
- CommandLine << " --test --log-id " << LogId;
+ CommandLine << " --test --log-id " << m_Name;
+ CommandLine << " --no-sentry";
}
if (m_OwnerPid.has_value())
@@ -544,7 +567,7 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
if (BasePort)
{
CommandLine << " --port " << BasePort;
- m_BasePort = BasePort;
+ m_BasePort = gsl::narrow_cast<uint16_t>(BasePort);
}
if (!m_TestDir.empty())
@@ -604,41 +627,8 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
{
if (!WaitUntilReady(WaitTimeoutMs))
{
- throw std::runtime_error(fmt::format("server start timeout after {}", NiceTimeSpanMs(WaitTimeoutMs)));
+ throw std::runtime_error(fmt::format("server start of {} timeout after {}", m_Name, NiceTimeSpanMs(WaitTimeoutMs)));
}
-
- // Determine effective base port
-
- ZenServerState State;
- if (!State.InitializeReadOnly())
- {
- // TODO: return success/error code instead?
- throw std::runtime_error("no zen state found");
- }
-
- const ZenServerState::ZenServerEntry* Entry = nullptr;
-
- if (BasePort)
- {
- Entry = State.Lookup(BasePort);
- }
- else
- {
- State.Snapshot([&](const ZenServerState::ZenServerEntry& InEntry) {
- if (InEntry.Pid == static_cast<uint32_t>(GetProcessId(ChildPid)))
- {
- Entry = &InEntry;
- }
- });
- }
-
- if (!Entry)
- {
- // TODO: return success/error code instead?
- throw std::runtime_error("no server entry found");
- }
-
- m_BasePort = Entry->EffectiveListenPort;
}
}
@@ -694,23 +684,73 @@ ZenServerInstance::Detach()
}
}
-void
+uint16_t
ZenServerInstance::WaitUntilReady()
{
while (m_ReadyEvent.Wait(100) == false)
{
if (!m_Process.IsRunning() || !m_Process.IsValid())
{
- ZEN_INFO("Wait abandoned by invalid process (running={})", m_Process.IsRunning());
- return;
+ ZEN_WARN("Wait abandoned by invalid process (running={})", m_Process.IsRunning());
+
+ return 0;
}
}
+
+ OnServerReady();
+
+ return m_BasePort;
}
bool
ZenServerInstance::WaitUntilReady(int Timeout)
{
- return m_ReadyEvent.Wait(Timeout);
+ if (m_ReadyEvent.Wait(Timeout))
+ {
+ OnServerReady();
+
+ return true;
+ }
+
+ return false;
+}
+
+void
+ZenServerInstance::OnServerReady()
+{
+ // Determine effective base port
+
+ ZenServerState State;
+ if (!State.InitializeReadOnly())
+ {
+ // TODO: return success/error code instead?
+ throw std::runtime_error("no zen state found");
+ }
+
+ const ZenServerState::ZenServerEntry* Entry = nullptr;
+
+ if (m_BasePort)
+ {
+ Entry = State.Lookup(m_BasePort);
+ }
+ else
+ {
+ State.Snapshot([&](const ZenServerState::ZenServerEntry& InEntry) {
+ if (InEntry.Pid == (uint32_t)m_Process.Pid())
+ {
+ Entry = &InEntry;
+ }
+ });
+ }
+
+ if (!Entry)
+ {
+ // TODO: return success/error code instead?
+ throw std::runtime_error("no server entry found");
+ }
+
+ m_BasePort = Entry->EffectiveListenPort;
+ CreateShutdownEvent(m_BasePort);
}
std::string
@@ -728,4 +768,14 @@ ZenServerInstance::SetTestDir(std::filesystem::path TestDir)
m_TestDir = TestDir;
}
+bool
+ZenServerInstance::IsRunning()
+{
+ if (!m_Process.IsValid())
+ {
+ return false;
+ }
+ return m_Process.IsRunning();
+}
+
} // namespace zen