diff options
| author | Martin Ridgers <[email protected]> | 2021-09-21 11:06:13 +0200 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-09-21 11:06:13 +0200 |
| commit | 68c951e0f440ffd483795dced737e88152c1a581 (patch) | |
| tree | 5c0910ca2a85b45fb05dba3ce457b7d156213894 /zenutil | |
| parent | Merge main into linux-mac (diff) | |
| parent | Trigger storage scrubbing pass at startup (diff) | |
| download | zen-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.cpp | 147 | ||||
| -rw-r--r-- | zenutil/zenutil.vcxproj | 5 | ||||
| -rw-r--r-- | zenutil/zenutil.vcxproj.filters | 5 |
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 |