aboutsummaryrefslogtreecommitdiff
path: root/zenutil
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2021-09-21 11:06:13 +0200
committerMartin Ridgers <[email protected]>2021-09-21 11:06:13 +0200
commit68c951e0f440ffd483795dced737e88152c1a581 (patch)
tree5c0910ca2a85b45fb05dba3ce457b7d156213894 /zenutil
parentMerge main into linux-mac (diff)
parentTrigger storage scrubbing pass at startup (diff)
downloadzen-68c951e0f440ffd483795dced737e88152c1a581.tar.xz
zen-68c951e0f440ffd483795dced737e88152c1a581.zip
Merged main into linux-mac
Diffstat (limited to 'zenutil')
-rw-r--r--zenutil/include/zenutil/zenserverprocess.h (renamed from zenutil/include/zenserverprocess.h)30
-rw-r--r--zenutil/zenserverprocess.cpp147
-rw-r--r--zenutil/zenutil.vcxproj5
-rw-r--r--zenutil/zenutil.vcxproj.filters5
4 files changed, 133 insertions, 54 deletions
diff --git a/zenutil/include/zenserverprocess.h b/zenutil/include/zenutil/zenserverprocess.h
index 7b41c8aba..09728aa1a 100644
--- a/zenutil/include/zenserverprocess.h
+++ b/zenutil/include/zenutil/zenserverprocess.h
@@ -5,11 +5,15 @@
#include <zencore/enumflags.h>
#include <zencore/logging.h>
#include <zencore/thread.h>
+#include <zencore/uid.h>
#include <gsl/gsl-lite.hpp>
#include <atomic>
#include <filesystem>
+#include <optional>
+
+namespace zen {
class ZenServerEnvironment
{
@@ -44,6 +48,9 @@ struct ZenServerInstance
[[nodiscard]] bool WaitUntilReady(int Timeout);
void EnableTermination() { m_Terminate = true; }
void EnableMesh() { m_MeshEnabled = true; }
+ void Detach();
+ inline int GetPid() { return m_Process.Pid(); }
+ inline void SetOwnerPid(int Pid) { m_OwnerPid = Pid; }
void SetTestDir(std::filesystem::path TestDir)
{
@@ -59,13 +66,14 @@ struct ZenServerInstance
private:
ZenServerEnvironment& m_Env;
- zen::ProcessHandle m_Process;
- zen::Event m_ReadyEvent;
- zen::Event m_ShutdownEvent;
+ ProcessHandle m_Process;
+ Event m_ReadyEvent;
+ Event m_ShutdownEvent;
bool m_Terminate = false;
std::filesystem::path m_TestDir;
bool m_MeshEnabled = false;
int m_BasePort = 0;
+ std::optional<int> m_OwnerPid;
void CreateShutdownEvent(int BasePort);
};
@@ -90,7 +98,9 @@ public:
std::atomic<uint16_t> ListenPort;
std::atomic<uint16_t> Flags;
uint8_t SessionId[12];
+ std::atomic<uint32_t> SponsorPids[32];
uint8_t Padding[12];
+ uint8_t Padding2[96];
enum class FlagsEnum : uint16_t
{
@@ -99,11 +109,13 @@ public:
FRIEND_ENUM_CLASS_FLAGS(FlagsEnum);
+ Oid GetSessionId() const { return Oid::FromMemory(SessionId); }
void Reset();
void SignalShutdownRequest();
+ bool AddSponsorProcess(uint32_t Pid);
};
- static_assert(sizeof(ZenServerEntry) == 32);
+ static_assert(sizeof(ZenServerEntry) == 256);
void Initialize();
[[nodiscard]] bool InitializeReadOnly();
@@ -111,10 +123,14 @@ public:
ZenServerEntry* Register(int ListenPort);
void Sweep();
void Snapshot(std::function<void(const ZenServerEntry&)>&& Callback);
+ inline bool IsReadOnly() const { return m_IsReadOnly; }
private:
- void* m_hMapFile = nullptr;
- ZenServerEntry* m_Data;
- int m_MaxEntryCount = 4096 / sizeof(ZenServerEntry);
+ void* m_hMapFile = nullptr;
+ ZenServerEntry* m_Data = nullptr;
+ int m_MaxEntryCount = 131072 / sizeof(ZenServerEntry);
ZenServerEntry* m_OurEntry = nullptr;
+ bool m_IsReadOnly = true;
};
+
+} // namespace zen
diff --git a/zenutil/zenserverprocess.cpp b/zenutil/zenserverprocess.cpp
index 7f4be2368..55b592ab1 100644
--- a/zenutil/zenserverprocess.cpp
+++ b/zenutil/zenserverprocess.cpp
@@ -1,11 +1,12 @@
// Copyright Epic Games, Inc. All Rights Reserved.
-#include "zenserverprocess.h"
+#include "zenutil/zenserverprocess.h"
#include <zencore/except.h>
#include <zencore/filesystem.h>
#include <zencore/fmtutils.h>
#include <zencore/logging.h>
+#include <zencore/session.h>
#include <zencore/string.h>
#include <atlbase.h>
@@ -16,44 +17,42 @@
//////////////////////////////////////////////////////////////////////////
+namespace zen {
+
namespace zenutil {
-class SecurityAttributes
-{
-public:
- inline SECURITY_ATTRIBUTES* Attributes() { return &m_Attributes; }
+ class SecurityAttributes
+ {
+ public:
+ inline SECURITY_ATTRIBUTES* Attributes() { return &m_Attributes; }
-protected:
- SECURITY_ATTRIBUTES m_Attributes{};
- SECURITY_DESCRIPTOR m_Sd{};
-};
+ protected:
+ SECURITY_ATTRIBUTES m_Attributes{};
+ SECURITY_DESCRIPTOR m_Sd{};
+ };
-// Security attributes which allows any user access
+ // Security attributes which allows any user access
-class AnyUserSecurityAttributes : public SecurityAttributes
-{
-public:
- AnyUserSecurityAttributes()
+ class AnyUserSecurityAttributes : public SecurityAttributes
{
- m_Attributes.nLength = sizeof m_Attributes;
- m_Attributes.bInheritHandle = false; // Disable inheritance
-
- const BOOL success = InitializeSecurityDescriptor(&m_Sd, SECURITY_DESCRIPTOR_REVISION);
-
- if (success)
+ public:
+ AnyUserSecurityAttributes()
{
- const BOOL bSetOk = SetSecurityDescriptorDacl(&m_Sd, TRUE, (PACL)NULL, FALSE);
+ m_Attributes.nLength = sizeof m_Attributes;
+ m_Attributes.bInheritHandle = false; // Disable inheritance
- if (bSetOk)
+ const BOOL Success = InitializeSecurityDescriptor(&m_Sd, SECURITY_DESCRIPTOR_REVISION);
+
+ if (Success)
{
+ if (!SetSecurityDescriptorDacl(&m_Sd, TRUE, (PACL)NULL, FALSE))
+ {
+ ThrowLastError("SetSecurityDescriptorDacl failed", std::source_location::current());
+ }
+
m_Attributes.lpSecurityDescriptor = &m_Sd;
}
- else
- {
- zen::ThrowLastError("SetSecurityDescriptorDacl failed", std::source_location::current());
- }
}
- }
-};
+ };
} // namespace zenutil
@@ -109,7 +108,7 @@ ZenServerState::Initialize()
if (hMap == NULL)
{
- zen::ThrowLastError("Could not open or create file mapping object for Zen server state");
+ ThrowLastError("Could not open or create file mapping object for Zen server state");
}
m_hMapFile = hMap;
@@ -123,10 +122,11 @@ ZenServerState::Initialize()
if (pBuf == NULL)
{
- zen::ThrowLastError("Could not map view of Zen server state");
+ ThrowLastError("Could not map view of Zen server state");
}
- m_Data = reinterpret_cast<ZenServerEntry*>(pBuf);
+ m_Data = reinterpret_cast<ZenServerEntry*>(pBuf);
+ m_IsReadOnly = false;
}
bool
@@ -149,7 +149,7 @@ ZenServerState::InitializeReadOnly()
if (pBuf == NULL)
{
- zen::ThrowLastError("Could not map view of Zen server state");
+ ThrowLastError("Could not map view of Zen server state");
}
m_Data = reinterpret_cast<ZenServerEntry*>(pBuf);
@@ -181,7 +181,7 @@ ZenServerState::Register(int ListenPort)
// Allocate an entry
- int Pid = zen::GetCurrentProcessId();
+ int Pid = GetCurrentProcessId();
for (int i = 0; i < m_MaxEntryCount; ++i)
{
@@ -199,6 +199,9 @@ ZenServerState::Register(int ListenPort)
Entry.Pid = Pid;
Entry.Flags = 0;
+ const Oid SesId = GetSessionId();
+ memcpy(Entry.SessionId, &SesId, sizeof SesId);
+
return &Entry;
}
}
@@ -215,13 +218,15 @@ ZenServerState::Sweep()
return;
}
+ ZEN_ASSERT(m_IsReadOnly == false);
+
for (int i = 0; i < m_MaxEntryCount; ++i)
{
ZenServerEntry& Entry = m_Data[i];
if (Entry.ListenPort)
{
- if (zen::IsProcessRunning(Entry.Pid) == false)
+ if (IsProcessRunning(Entry.Pid) == false)
{
ZEN_DEBUG("Sweep - pid {} not running, reclaiming entry (port {})", Entry.Pid, Entry.ListenPort);
@@ -264,6 +269,30 @@ ZenServerState::ZenServerEntry::SignalShutdownRequest()
Flags |= uint16_t(FlagsEnum::kShutdownPlease);
}
+bool
+ZenServerState::ZenServerEntry::AddSponsorProcess(uint32_t PidToAdd)
+{
+ for (std::atomic<uint32_t>& PidEntry : SponsorPids)
+ {
+ if (PidEntry.load(std::memory_order::memory_order_relaxed) == 0)
+ {
+ uint32_t Expected = 0;
+ if (PidEntry.compare_exchange_strong(Expected, uint16_t(PidToAdd)))
+ {
+ // Success!
+ return true;
+ }
+ }
+ else if (PidEntry.load(std::memory_order::memory_order_relaxed) == PidToAdd)
+ {
+ // Success, the because pid is already in the list
+ return true;
+ }
+ }
+
+ return false;
+}
+
//////////////////////////////////////////////////////////////////////////
std::atomic<int> TestCounter{0};
@@ -294,7 +323,7 @@ ZenServerEnvironment::InitializeForTest(std::filesystem::path ProgramBaseDir, st
ZEN_INFO("Program base dir is '{}'", ProgramBaseDir);
ZEN_INFO("Cleaning test base dir '{}'", TestBaseDir);
- zen::DeleteDirectories(TestBaseDir.c_str());
+ DeleteDirectories(TestBaseDir.c_str());
m_IsTestInstance = true;
m_IsInitialized = true;
@@ -305,14 +334,14 @@ ZenServerEnvironment::CreateNewTestDir()
{
using namespace std::literals;
- zen::ExtendableWideStringBuilder<256> TestDir;
+ ExtendableWideStringBuilder<256> TestDir;
TestDir << "test"sv << int64_t(++TestCounter);
std::filesystem::path TestPath = m_TestBaseDir / TestDir.c_str();
ZEN_INFO("Creating new test dir @ '{}'", TestPath);
- zen::CreateDirectories(TestPath.c_str());
+ CreateDirectories(TestPath.c_str());
return TestPath;
}
@@ -377,16 +406,16 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
const int MyPid = _getpid();
const int ChildId = ++ChildIdCounter;
- zen::ExtendableStringBuilder<32> ChildEventName;
+ ExtendableStringBuilder<32> ChildEventName;
ChildEventName << "Zen_Child_" << ChildId;
- zen::NamedEvent ChildEvent{ChildEventName};
+ NamedEvent ChildEvent{ChildEventName};
CreateShutdownEvent(BasePort);
- zen::ExtendableStringBuilder<32> LogId;
+ ExtendableStringBuilder<32> LogId;
LogId << "Zen" << ChildId;
- zen::ExtendableWideStringBuilder<512> CommandLine;
+ ExtendableWideStringBuilder<512> CommandLine;
CommandLine << "\"";
CommandLine.Append(Executable.c_str());
CommandLine << "\"";
@@ -395,7 +424,17 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
if (IsTest)
{
- CommandLine << " --test --owner-pid " << MyPid << " --log-id " << LogId;
+ if (!m_OwnerPid.has_value())
+ {
+ m_OwnerPid = MyPid;
+ }
+
+ CommandLine << " --test --log-id " << LogId;
+ }
+
+ if (m_OwnerPid.has_value())
+ {
+ CommandLine << " --owner-pid " << m_OwnerPid.value();
}
CommandLine << " --child-id " << ChildEventName;
@@ -515,10 +554,10 @@ ZenServerInstance::SpawnServer(int BasePort, std::string_view AdditionalServerAr
void
ZenServerInstance::CreateShutdownEvent(int BasePort)
{
- zen::ExtendableStringBuilder<32> ChildShutdownEventName;
+ ExtendableStringBuilder<32> ChildShutdownEventName;
ChildShutdownEventName << "Zen_" << BasePort;
ChildShutdownEventName << "_Shutdown";
- zen::NamedEvent ChildShutdownEvent{ChildShutdownEventName};
+ NamedEvent ChildShutdownEvent{ChildShutdownEventName};
m_ShutdownEvent = std::move(ChildShutdownEvent);
}
@@ -554,9 +593,25 @@ ZenServerInstance::AttachToRunningServer(int BasePort)
}
void
+ZenServerInstance::Detach()
+{
+ if (m_Process.IsValid())
+ {
+ m_Process.Reset();
+ m_ShutdownEvent.Close();
+ }
+}
+
+void
ZenServerInstance::WaitUntilReady()
{
- m_ReadyEvent.Wait();
+ while (m_ReadyEvent.Wait(100) == false)
+ {
+ if (!m_Process.IsRunning() || !m_Process.IsValid())
+ {
+ return;
+ }
+ }
}
bool
@@ -574,3 +629,5 @@ ZenServerInstance::GetBaseUri() const
return "http://localhost:{}"_format(m_BasePort);
}
+
+} // namespace zen
diff --git a/zenutil/zenutil.vcxproj b/zenutil/zenutil.vcxproj
index fcb27dff3..3bf6111f7 100644
--- a/zenutil/zenutil.vcxproj
+++ b/zenutil/zenutil.vcxproj
@@ -100,13 +100,16 @@
<ClCompile Include="zenserverprocess.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="include\zenserverprocess.h" />
+ <ClInclude Include="include\zenutil\zenserverprocess.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\zencore\zencore.vcxproj">
<Project>{d75bf9ab-c61e-4fff-ad59-1563430f05e2}</Project>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <None Include="xmake.lua" />
+ </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/zenutil/zenutil.vcxproj.filters b/zenutil/zenutil.vcxproj.filters
index ca1414842..9952e7159 100644
--- a/zenutil/zenutil.vcxproj.filters
+++ b/zenutil/zenutil.vcxproj.filters
@@ -4,6 +4,9 @@
<ClCompile Include="zenserverprocess.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="include\zenserverprocess.h" />
+ <ClInclude Include="include\zenutil\zenserverprocess.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="xmake.lua" />
</ItemGroup>
</Project> \ No newline at end of file