From f38c649923e5d9cf793e5b3085241af0dbec4891 Mon Sep 17 00:00:00 2001 From: Tres Finocchiaro Date: Mon, 3 Feb 2025 14:18:02 -0500 Subject: [PATCH] SharedMemory: Make key optional, default to shorter UID on macOS (#7681) * SharedMemory: Make key optional, shorter on macOS * Add getters for shared memory size * macOS: Fix linking regression for RemoteZynAddSubFx introduced with #7252 --------- Co-authored-by: Dalton Messmer --- cmake/apple/MacDeployQt.cmake | 4 +-- include/RemotePluginBase.h | 3 +- include/SharedMemory.h | 18 +++++++++++ src/common/SharedMemory.cpp | 55 ++++++++++++++++++++++++++++++---- src/core/RemotePlugin.cpp | 2 +- src/core/VstSyncController.cpp | 3 +- 6 files changed, 73 insertions(+), 12 deletions(-) diff --git a/cmake/apple/MacDeployQt.cmake b/cmake/apple/MacDeployQt.cmake index bee22cf42..acd7aae8d 100644 --- a/cmake/apple/MacDeployQt.cmake +++ b/cmake/apple/MacDeployQt.cmake @@ -107,8 +107,8 @@ file(GLOB LIBS "${APP}/Contents/lib/${lmms}/*.so") # Inform macdeployqt about LADSPA plugins; may depend on bundled fftw3f, etc. file(GLOB LADSPA "${APP}/Contents/lib/${lmms}/ladspa/*.so") -# Inform linuxdeploy about remote plugins -list(APPEND REMOTE_PLUGINS "${APP}/Contents/MacOS/*Remote*") +# Inform macdeployqt about remote plugins +file(GLOB REMOTE_PLUGINS "${APP}/Contents/MacOS/*Remote*") # Collect, sort and dedupe all libraries list(APPEND LIBS ${LADSPA}) diff --git a/include/RemotePluginBase.h b/include/RemotePluginBase.h index bbf14207a..787742fc0 100644 --- a/include/RemotePluginBase.h +++ b/include/RemotePluginBase.h @@ -71,7 +71,6 @@ #include #include #include -#include #ifndef SYNC_WITH_SHM_FIFO #include @@ -125,7 +124,7 @@ public: m_master( true ), m_lockDepth( 0 ) { - m_data.create(QUuid::createUuid().toString().toStdString()); + m_data.create(); m_data->startPtr = m_data->endPtr = 0; static int k = 0; m_data->dataSem.semKey = ( getpid()<<10 ) + ++k; diff --git a/include/SharedMemory.h b/include/SharedMemory.h index c2790c78b..3ed1330d4 100644 --- a/include/SharedMemory.h +++ b/include/SharedMemory.h @@ -44,6 +44,7 @@ public: SharedMemoryData() noexcept; SharedMemoryData(std::string&& key, bool readOnly); SharedMemoryData(std::string&& key, std::size_t size, bool readOnly); + SharedMemoryData(std::size_t size, bool readOnly); ~SharedMemoryData(); SharedMemoryData(SharedMemoryData&& other) noexcept; @@ -64,6 +65,7 @@ public: const std::string& key() const noexcept { return m_key; } void* get() const noexcept { return m_ptr; } + std::size_t size_bytes() const noexcept; private: std::string m_key; @@ -95,6 +97,11 @@ public: m_data = detail::SharedMemoryData{std::move(key), sizeof(T), std::is_const_v}; } + void create() + { + m_data = detail::SharedMemoryData{sizeof(T), std::is_const_v}; + } + void detach() noexcept { m_data = detail::SharedMemoryData{}; @@ -103,6 +110,9 @@ public: const std::string& key() const noexcept { return m_data.key(); } T* get() const noexcept { return static_cast(m_data.get()); } + std::size_t size() const noexcept { return get() ? 1 : 0; } + std::size_t size_bytes() const noexcept { return get() ? sizeof(T) : 0; } + T* operator->() const noexcept { return get(); } T& operator*() const noexcept { return *get(); } explicit operator bool() const noexcept { return get() != nullptr; } @@ -132,6 +142,11 @@ public: m_data = detail::SharedMemoryData{std::move(key), size * sizeof(T), std::is_const_v}; } + void create(std::size_t size) + { + m_data = detail::SharedMemoryData{size * sizeof(T), std::is_const_v}; + } + void detach() noexcept { m_data = detail::SharedMemoryData{}; @@ -140,6 +155,9 @@ public: const std::string& key() const noexcept { return m_data.key(); } T* get() const noexcept { return static_cast(m_data.get()); } + std::size_t size() const noexcept { return m_data.size_bytes() / sizeof(T); } + std::size_t size_bytes() const noexcept { return m_data.size_bytes(); } + T& operator[](std::size_t index) const noexcept { return get()[index]; } explicit operator bool() const noexcept { return get() != nullptr; } diff --git a/src/common/SharedMemory.cpp b/src/common/SharedMemory.cpp index 19d3dba1b..6ef815c6d 100644 --- a/src/common/SharedMemory.cpp +++ b/src/common/SharedMemory.cpp @@ -23,6 +23,7 @@ #include "SharedMemory.h" +#include #include #include @@ -75,7 +76,7 @@ class SharedMemoryImpl { public: SharedMemoryImpl(const std::string& key, bool readOnly) : - m_key{"/" + key} + m_key{'/' + key} { const auto openFlags = readOnly ? O_RDONLY : O_RDWR; const auto fd = FileDescriptor{ @@ -93,7 +94,7 @@ public: } SharedMemoryImpl(const std::string& key, std::size_t size, bool readOnly) : - m_key{"/" + key}, + m_key{'/' + key}, m_size{size} { const auto fd = FileDescriptor{ @@ -120,11 +121,12 @@ public: } auto get() const noexcept -> void* { return m_mapping; } + auto size_bytes() const noexcept -> std::size_t { return m_size; } private: std::string m_key; - std::size_t m_size; - void* m_mapping; + std::size_t m_size = 0; + void* m_mapping = nullptr; ShmObject m_object; }; @@ -163,9 +165,18 @@ public: m_view.reset(MapViewOfFile(m_mapping.get(), access, 0, 0, 0)); if (!m_view) { throwLastError("SharedMemoryImpl: MapViewOfFile() failed"); } + + MEMORY_BASIC_INFORMATION mbi; + if (VirtualQuery(m_view.get(), &mbi, sizeof(mbi)) == 0) + { + throwLastError("SharedMemoryImpl: VirtualQuery() failed"); + } + + m_size = static_cast(mbi.RegionSize); } - SharedMemoryImpl(const std::string& key, std::size_t size, bool readOnly) + SharedMemoryImpl(const std::string& key, std::size_t size, bool readOnly) : + m_size{size} { const auto [high, low] = sizeToHighAndLow(size); m_mapping.reset(CreateFileMappingA(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, high, low, key.c_str())); @@ -186,14 +197,39 @@ public: auto operator=(const SharedMemoryImpl&) -> SharedMemoryImpl& = delete; auto get() const noexcept -> void* { return m_view.get(); } + auto size_bytes() const noexcept -> std::size_t { return m_size; } private: UniqueHandle m_mapping; FileView m_view; + std::size_t m_size = 0; }; #endif +namespace { + +auto createKey() -> std::string +{ + // Max length (minus prepended '/') on macOS (PSHMNAMLEN=31) + constexpr int length = 30; + + std::string key; + std::random_device rd; + auto gen = std::mt19937{rd()}; // mersenne twister, seeded + auto distrib = std::uniform_int_distribution{0, 15}; // hex range (0-15) + + key.reserve(length + 1); + for (int i = 0; i < length; ++i) + { + key += "0123456789ABCDEF"[distrib(gen)]; + } + + return key; +} + +} // namespace + SharedMemoryData::SharedMemoryData() noexcept = default; SharedMemoryData::SharedMemoryData(std::string&& key, bool readOnly) : @@ -208,6 +244,10 @@ SharedMemoryData::SharedMemoryData(std::string&& key, std::size_t size, bool rea m_ptr{m_impl->get()} { } +SharedMemoryData::SharedMemoryData(std::size_t size, bool readOnly) : + SharedMemoryData{createKey(), size, readOnly} +{ } + SharedMemoryData::~SharedMemoryData() = default; SharedMemoryData::SharedMemoryData(SharedMemoryData&& other) noexcept : @@ -216,4 +256,9 @@ SharedMemoryData::SharedMemoryData(SharedMemoryData&& other) noexcept : m_ptr{std::exchange(other.m_ptr, nullptr)} { } +auto SharedMemoryData::size_bytes() const noexcept -> std::size_t +{ + return m_impl ? m_impl->size_bytes() : 0; +} + } // namespace lmms::detail diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index 28f5f915a..e0eeff524 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -485,7 +485,7 @@ void RemotePlugin::resizeSharedProcessingMemory() const size_t s = (m_inputCount + m_outputCount) * Engine::audioEngine()->framesPerPeriod(); try { - m_audioBuffer.create(QUuid::createUuid().toString().toStdString(), s); + m_audioBuffer.create(s); } catch (const std::runtime_error& error) { diff --git a/src/core/VstSyncController.cpp b/src/core/VstSyncController.cpp index 79344a5b5..984b1b32c 100644 --- a/src/core/VstSyncController.cpp +++ b/src/core/VstSyncController.cpp @@ -28,7 +28,6 @@ #include #include -#include #include "AudioEngine.h" #include "ConfigManager.h" @@ -44,7 +43,7 @@ VstSyncController::VstSyncController() { try { - m_syncData.create(QUuid::createUuid().toString().toStdString()); + m_syncData.create(); } catch (const std::runtime_error& error) {