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 <messmer.dalton@gmail.com>
This commit is contained in:
Tres Finocchiaro
2025-02-03 14:18:02 -05:00
committed by GitHub
parent 36c1deae42
commit f38c649923
6 changed files with 73 additions and 12 deletions

View File

@@ -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})

View File

@@ -71,7 +71,6 @@
#include <QProcess>
#include <QThread>
#include <QString>
#include <QUuid>
#ifndef SYNC_WITH_SHM_FIFO
#include <poll.h>
@@ -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;

View File

@@ -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<T>};
}
void create()
{
m_data = detail::SharedMemoryData{sizeof(T), std::is_const_v<T>};
}
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<T*>(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<T>};
}
void create(std::size_t size)
{
m_data = detail::SharedMemoryData{size * sizeof(T), std::is_const_v<T>};
}
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<T*>(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; }

View File

@@ -23,6 +23,7 @@
#include "SharedMemory.h"
#include <random>
#include <system_error>
#include <utility>
@@ -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<std::size_t>(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

View File

@@ -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)
{

View File

@@ -28,7 +28,6 @@
#include <stdexcept>
#include <QDebug>
#include <QUuid>
#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)
{