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.cpp72
1 files changed, 60 insertions, 12 deletions
diff --git a/src/zenutil/zenserverprocess.cpp b/src/zenutil/zenserverprocess.cpp
index 2b27b2d8b..2d4334ffa 100644
--- a/src/zenutil/zenserverprocess.cpp
+++ b/src/zenutil/zenserverprocess.cpp
@@ -181,7 +181,7 @@ ZenServerState::Initialize()
ThrowLastError("Could not map view of Zen server state");
}
#else
- int Fd = shm_open("/UnrealEngineZen", O_RDWR | O_CREAT | O_CLOEXEC, geteuid() == 0 ? 0766 : 0666);
+ int Fd = shm_open("/UnrealEngineZen", O_RDWR | O_CREAT, geteuid() == 0 ? 0766 : 0666);
if (Fd < 0)
{
// Work around a potential issue if the service user is changed in certain configurations.
@@ -191,7 +191,7 @@ ZenServerState::Initialize()
// shared memory object and retry, we'll be able to get past shm_open() so long as we have
// the appropriate permissions to create the shared memory object.
shm_unlink("/UnrealEngineZen");
- Fd = shm_open("/UnrealEngineZen", O_RDWR | O_CREAT | O_CLOEXEC, geteuid() == 0 ? 0766 : 0666);
+ Fd = shm_open("/UnrealEngineZen", O_RDWR | O_CREAT, geteuid() == 0 ? 0766 : 0666);
if (Fd < 0)
{
ThrowLastError("Could not open a shared memory object");
@@ -244,7 +244,7 @@ ZenServerState::InitializeReadOnly()
ThrowLastError("Could not map view of Zen server state");
}
#else
- int Fd = shm_open("/UnrealEngineZen", O_RDONLY | O_CLOEXEC, 0666);
+ int Fd = shm_open("/UnrealEngineZen", O_RDONLY, 0666);
if (Fd < 0)
{
return false;
@@ -267,6 +267,8 @@ ZenServerState::InitializeReadOnly()
ZenServerState::ZenServerEntry*
ZenServerState::Lookup(int DesiredListenPort) const
{
+ const uint32_t OurPid = GetCurrentProcessId();
+
for (int i = 0; i < m_MaxEntryCount; ++i)
{
uint16_t EntryPort = m_Data[i].DesiredListenPort;
@@ -274,6 +276,14 @@ ZenServerState::Lookup(int DesiredListenPort) const
{
if (DesiredListenPort == 0 || (EntryPort == DesiredListenPort))
{
+ // If the entry's PID matches our own but we haven't registered yet,
+ // this is a stale entry from a previous process incarnation (e.g. PID 1
+ // reuse after unclean shutdown in k8s). Skip it.
+ if (m_Data[i].Pid == OurPid && m_OurEntry == nullptr)
+ {
+ continue;
+ }
+
std::error_code _;
if (IsProcessRunning(m_Data[i].Pid, _))
{
@@ -289,6 +299,8 @@ ZenServerState::Lookup(int DesiredListenPort) const
ZenServerState::ZenServerEntry*
ZenServerState::LookupByEffectivePort(int Port) const
{
+ const uint32_t OurPid = GetCurrentProcessId();
+
for (int i = 0; i < m_MaxEntryCount; ++i)
{
uint16_t EntryPort = m_Data[i].EffectiveListenPort;
@@ -296,6 +308,11 @@ ZenServerState::LookupByEffectivePort(int Port) const
{
if (EntryPort == Port)
{
+ if (m_Data[i].Pid == OurPid && m_OurEntry == nullptr)
+ {
+ continue;
+ }
+
std::error_code _;
if (IsProcessRunning(m_Data[i].Pid, _))
{
@@ -358,12 +375,26 @@ ZenServerState::Sweep()
ZEN_ASSERT(m_IsReadOnly == false);
+ const uint32_t OurPid = GetCurrentProcessId();
+
for (int i = 0; i < m_MaxEntryCount; ++i)
{
ZenServerEntry& Entry = m_Data[i];
if (Entry.DesiredListenPort)
{
+ // If the entry's PID matches our own but we haven't registered yet,
+ // this is a stale entry from a previous process incarnation (e.g. PID 1
+ // reuse after unclean shutdown in k8s). Reclaim it.
+ if (Entry.Pid == OurPid && m_OurEntry == nullptr)
+ {
+ ZEN_CONSOLE_DEBUG("Sweep - pid {} matches current process but no registration yet, reclaiming stale entry (port {})",
+ Entry.Pid.load(),
+ Entry.DesiredListenPort.load());
+ Entry.Reset();
+ continue;
+ }
+
std::error_code ErrorCode;
if (Entry.Pid != 0 && IsProcessRunning(Entry.Pid, ErrorCode) == false)
{
@@ -620,7 +651,7 @@ ZenServerInstanceInfo::Create(const Oid& SessionId, const InstanceInfoData& Data
ThrowLastError("Could not map instance info shared memory");
}
#else
- int Fd = shm_open(Name.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666);
+ int Fd = shm_open(Name.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
if (Fd < 0)
{
ThrowLastError("Could not create instance info shared memory");
@@ -687,7 +718,7 @@ ZenServerInstanceInfo::OpenReadOnly(const Oid& SessionId)
return false;
}
#else
- int Fd = shm_open(Name.c_str(), O_RDONLY | O_CLOEXEC, 0666);
+ int Fd = shm_open(Name.c_str(), O_RDONLY, 0666);
if (Fd < 0)
{
return false;
@@ -1082,8 +1113,23 @@ ZenServerInstance::SpawnServerInternal(int ChildId, std::string_view ServerArgs,
ChildEventName << "Zen_Child_" << ChildId;
NamedEvent ChildEvent{ChildEventName};
+ const std::filesystem::path BaseDir = m_Env.ProgramBaseDir();
+ const std::filesystem::path Executable =
+ m_ServerExecutablePath.empty() ? (BaseDir / "zenserver" ZEN_EXE_SUFFIX_LITERAL) : m_ServerExecutablePath;
+
ExtendableStringBuilder<512> CommandLine;
- CommandLine << "zenserver" ZEN_EXE_SUFFIX_LITERAL; // see CreateProc() call for actual binary path
+ {
+ const std::string ExeUtf8 = PathToUtf8(Executable);
+ constexpr AsciiSet QuoteChars = " \t\"";
+ if (AsciiSet::HasAny(ExeUtf8.c_str(), QuoteChars))
+ {
+ CommandLine << '"' << ExeUtf8 << '"';
+ }
+ else
+ {
+ CommandLine << ExeUtf8;
+ }
+ }
if (m_ServerMode == ServerMode::kHubServer)
{
@@ -1096,6 +1142,11 @@ ZenServerInstance::SpawnServerInternal(int ChildId, std::string_view ServerArgs,
CommandLine << " --child-id " << ChildEventName;
+ if (!m_EnableExecutionHistory)
+ {
+ CommandLine << " --enable-execution-history=false";
+ }
+
if (!ServerArgs.empty())
{
CommandLine << " " << ServerArgs;
@@ -1110,10 +1161,6 @@ ZenServerInstance::SpawnServerInternal(int ChildId, std::string_view ServerArgs,
{
CreationFlags |= CreateProcOptions::Flag_NewConsole;
}
-
- const std::filesystem::path BaseDir = m_Env.ProgramBaseDir();
- const std::filesystem::path Executable =
- m_ServerExecutablePath.empty() ? (BaseDir / "zenserver" ZEN_EXE_SUFFIX_LITERAL) : m_ServerExecutablePath;
const std::filesystem::path OutputPath = (OpenConsole || m_Env.IsPassthroughOutput())
? std::filesystem::path{}
: std::filesystem::temp_directory_path() / ("zenserver_" + m_Name + ".log");
@@ -1583,7 +1630,7 @@ ValidateLockFileInfo(const LockFileInfo& Info, std::string& OutReason)
std::optional<int>
StartupZenServer(LoggerRef LogRef, const StartupZenServerOptions& Options)
{
- auto Log = [&LogRef]() { return LogRef; };
+ ZEN_SCOPED_LOG(LogRef);
// Check if a matching server is already running
{
@@ -1616,6 +1663,7 @@ StartupZenServer(LoggerRef LogRef, const StartupZenServerOptions& Options)
ZenServerEnvironment ServerEnvironment;
ServerEnvironment.Initialize(ProgramBaseDir);
ZenServerInstance Server(ServerEnvironment, Options.Mode);
+ Server.SetEnableExecutionHistory(Options.EnableExecutionHistory);
std::string ServerArguments(Options.ExtraArgs);
if ((Options.Port != 0) && (ServerArguments.find("--port") == std::string::npos))
@@ -1653,7 +1701,7 @@ ShutdownZenServer(LoggerRef LogRef,
ZenServerState::ZenServerEntry* Entry,
const std::filesystem::path& ProgramBaseDir)
{
- auto Log = [&LogRef]() { return LogRef; };
+ ZEN_SCOPED_LOG(LogRef);
int EntryPort = (int)Entry->DesiredListenPort.load();
const uint32_t ServerProcessPid = Entry->Pid.load();
try