diff options
| author | Martin Ridgers <[email protected]> | 2021-10-29 14:31:23 +0200 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-10-29 14:33:08 +0200 |
| commit | a4e456ef7a9ff6fc37b0bd4ec0dfc25a282cafb3 (patch) | |
| tree | 81ee94ea6ce6229aa80c4284e120d3720c2537eb /zenutil/zenserverprocess.cpp | |
| parent | Use zen::GetCurrentProcessId() instead of MS' _getpid() (diff) | |
| download | zen-a4e456ef7a9ff6fc37b0bd4ec0dfc25a282cafb3.tar.xz zen-a4e456ef7a9ff6fc37b0bd4ec0dfc25a282cafb3.zip | |
Implemented ZenServerState's shared memory layer for POSIX
Diffstat (limited to 'zenutil/zenserverprocess.cpp')
| -rw-r--r-- | zenutil/zenserverprocess.cpp | 95 |
1 files changed, 71 insertions, 24 deletions
diff --git a/zenutil/zenserverprocess.cpp b/zenutil/zenserverprocess.cpp index ab547b98c..1974772d2 100644 --- a/zenutil/zenserverprocess.cpp +++ b/zenutil/zenserverprocess.cpp @@ -8,13 +8,17 @@ #include <zencore/logging.h> #include <zencore/session.h> #include <zencore/string.h> +#include <zencore/thread.h> +#include <atomic> #include <source_location> #if ZEN_PLATFORM_WINDOWS # include <atlbase.h> # include <shellapi.h> # include <zencore/windows.h> +#else +# include <sys/mman.h> #endif ////////////////////////////////////////////////////////////////////////// @@ -22,6 +26,7 @@ namespace zen { namespace zenutil { +#if ZEN_PLATFORM_WINDOWS class SecurityAttributes { public: @@ -55,6 +60,7 @@ namespace zenutil { } } }; +#endif // ZEN_PLATFORM_WINDOWS } // namespace zenutil @@ -74,59 +80,85 @@ ZenServerState::~ZenServerState() m_OurEntry = nullptr; } +#if ZEN_PLATFORM_WINDOWS if (m_Data) { UnmapViewOfFile(m_Data); - m_Data = nullptr; } if (m_hMapFile) { CloseHandle(m_hMapFile); } +#else + if (m_Data != nullptr) + { + munmap(m_Data, m_MaxEntryCount * sizeof(ZenServerEntry)); + } + + int Fd = int(intptr_t(m_hMapFile)); + close(Fd); +#endif + + m_Data = nullptr; } void ZenServerState::Initialize() { + size_t MapSize = m_MaxEntryCount * sizeof(ZenServerEntry); + +#if ZEN_PLATFORM_WINDOWS // TODO: there's a small chance of a race here, this logic could be tightened up with a mutex to // ensure only a single process at a time creates the mapping - if (HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"Global\\ZenMap")) - { - m_hMapFile = hMap; - } - else + HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"Global\\ZenMap"); + if (hMap == NULL) { // Security attributes to enable any user to access state zenutil::AnyUserSecurityAttributes Attrs; - hMap = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file - Attrs.Attributes(), // allow anyone to access - PAGE_READWRITE, // read/write access - 0, // maximum object size (high-order DWORD) - m_MaxEntryCount * sizeof(ZenServerEntry), // maximum object size (low-order DWORD) - L"Global\\ZenMap"); // name of mapping object + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file + Attrs.Attributes(), // allow anyone to access + PAGE_READWRITE, // read/write access + 0, // maximum object size (high-order DWORD) + MapSize, // maximum object size (low-order DWORD) + L"Global\\ZenMap"); // name of mapping object if (hMap == NULL) { ThrowLastError("Could not open or create file mapping object for Zen server state"); } - - m_hMapFile = hMap; } - void* pBuf = MapViewOfFile(m_hMapFile, // handle to map object + void* pBuf = MapViewOfFile(hMap, // handle to map object FILE_MAP_ALL_ACCESS, // read/write permission 0, // offset high 0, // offset low - m_MaxEntryCount * sizeof(ZenServerEntry)); + MapSize); if (pBuf == NULL) { ThrowLastError("Could not map view of Zen server state"); } +#else + int Fd = shm_open("UnrealEngineZen", O_RDWR|O_CREAT, 0666); + if (Fd < 0) + { + ThrowLastError("Could not open a shared memory object"); + } + void* hMap = (void*)intptr_t(Fd); + ftruncate(Fd, MapSize); + + void* pBuf = mmap(nullptr, MapSize, PROT_READ|PROT_WRITE, MAP_SHARED, Fd, 0); + if (pBuf == MAP_FAILED) + { + ThrowLastError("Could not map view of Zen server state"); + } +#endif + + m_hMapFile = hMap; m_Data = reinterpret_cast<ZenServerEntry*>(pBuf); m_IsReadOnly = false; } @@ -134,27 +166,42 @@ ZenServerState::Initialize() bool ZenServerState::InitializeReadOnly() { - if (HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"Global\\ZenMap")) - { - m_hMapFile = hMap; - } - else + size_t MapSize = m_MaxEntryCount * sizeof(ZenServerEntry); + +#if ZEN_PLATFORM_WINDOWS + HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, L"Global\\ZenMap"); + if (hMap == NULL) { return false; } - void* pBuf = MapViewOfFile(m_hMapFile, // handle to map object + void* pBuf = MapViewOfFile(hMap, // handle to map object FILE_MAP_READ, // read permission 0, // offset high 0, // offset low - m_MaxEntryCount * sizeof(ZenServerEntry)); + MapSize); if (pBuf == NULL) { ThrowLastError("Could not map view of Zen server state"); } +#else + int Fd = shm_open("UnrealEngineZen", O_RDONLY, 0666); + if (Fd < 0) + { + return false; + } + void* hMap = (void*)intptr_t(Fd); + + void* pBuf = mmap(nullptr, MapSize, PROT_READ, MAP_PRIVATE, Fd, 0); + if (pBuf == MAP_FAILED) + { + ThrowLastError("Could not map read-only view of Zen server state"); + } +#endif - m_Data = reinterpret_cast<ZenServerEntry*>(pBuf); + m_hMapFile = hMap; + m_Data = reinterpret_cast<ZenServerEntry*>(pBuf); return true; } |