Fix a plugin crash on closing UI

This commit is contained in:
Jean Pierre Cimalando 2020-09-04 10:30:03 +02:00
parent 026875ae98
commit 174194ebd2
3 changed files with 63 additions and 58 deletions

View file

@ -74,6 +74,12 @@ typedef std::unique_ptr<CFrame, FrameHolderDeleter> FrameHolder;
/// ///
struct sfizz_ui_t : EditorController, VSTGUIEditorInterface { struct sfizz_ui_t : EditorController, VSTGUIEditorInterface {
#if LINUX
SoHandleInitializer soHandleInitializer;
#endif
#if MAC
BundleRefInitializer bundleRefInitializer;
#endif
LV2UI_Write_Function write = nullptr; LV2UI_Write_Function write = nullptr;
LV2UI_Controller con = nullptr; LV2UI_Controller con = nullptr;
LV2_URID_Map *map = nullptr; LV2_URID_Map *map = nullptr;
@ -369,13 +375,6 @@ LV2_SYMBOL_EXPORT
const LV2UI_Descriptor * const LV2UI_Descriptor *
lv2ui_descriptor(uint32_t index) lv2ui_descriptor(uint32_t index)
{ {
#if LINUX
VSTGUI::initializeSoHandle();
#endif
#if MAC
VSTGUI::initializeBundleRef();
#endif
switch (index) switch (index)
{ {
case 0: case 0:

View file

@ -11,6 +11,7 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <stdexcept>
#if LINUX #if LINUX
#include <dlfcn.h> #include <dlfcn.h>
#include <poll.h> #include <poll.h>
@ -143,36 +144,31 @@ namespace VSTGUI
{ {
void* soHandle = nullptr; void* soHandle = nullptr;
static volatile bool soHandleInitialized = false; static volatile size_t soHandleCount = 0;
static std::mutex soHandleMutex; static std::mutex soHandleMutex;
struct Dl_handle_deleter SoHandleInitializer::SoHandleInitializer()
{ {
void operator()(void* x) const noexcept std::lock_guard<std::mutex> lock(soHandleMutex);
{ if (soHandleCount++ == 0) {
dlclose(x); Dl_info info;
} if (dladdr((void*)&lv2ui_descriptor, &info))
}; soHandle = dlopen(info.dli_fname, RTLD_LAZY);
static std::unique_ptr<void, Dl_handle_deleter> soHandlePointer; if (!soHandle)
} // namespace VSTGUI throw std::runtime_error("SoHandleInitializer");
}
void VSTGUI::initializeSoHandle()
{
if (VSTGUI::soHandleInitialized)
return;
std::lock_guard<std::mutex> lock(VSTGUI::soHandleMutex);
if (VSTGUI::soHandleInitialized)
return;
Dl_info info;
if (dladdr((void*)&lv2ui_descriptor, &info))
{
VSTGUI::soHandle = dlopen(info.dli_fname, RTLD_LAZY);
VSTGUI::soHandlePointer.reset(VSTGUI::soHandle);
}
VSTGUI::soHandleInitialized = true;
} }
SoHandleInitializer::~SoHandleInitializer()
{
std::lock_guard<std::mutex> lock(soHandleMutex);
if (--soHandleCount == 0) {
dlclose(soHandle);
soHandle = nullptr;
}
}
} // namespace VSTGUI
#endif #endif
/// ///
@ -194,31 +190,27 @@ namespace VSTGUI
{ {
void* gBundleRef = nullptr; void* gBundleRef = nullptr;
static volatile bool gBundleRefInitialized = false; static volatile size_t gBundleRefCount = 0;
static std::mutex gBundleRefMutex; static std::mutex gBundleRefMutex;
struct CFBundle_deleter { BundleRefInitializer::BundleRefInitializer()
void operator()(CFBundleRef x) const noexcept
{
CFRelease(x);
}
};
static std::unique_ptr<__CFBundle, CFBundle_deleter> gBundleRefPointer;
} // namespace VSTGUI
void VSTGUI::initializeBundleRef()
{ {
if (VSTGUI::gBundleRefInitialized) std::lock_guard<std::mutex> lock(gBundleRefMutex);
return; if (bundleRefCount++ == 0) {
gBundleRef = GetPluginBundle();
std::lock_guard<std::mutex> lock(VSTGUI::gBundleRefMutex); if (!gBundleRef)
if (VSTGUI::gBundleRefInitialized) throw std::runtime_error("BundleRefInitializer");
return; }
CFBundleRef bundleRef = GetPluginBundle();
VSTGUI::gBundleRef = bundleRef;
VSTGUI::gBundleRefPointer.reset(bundleRef);
VSTGUI::gBundleRefInitialized = true;
} }
BundleRefInitializer::~BundleRefInitializer()
{
std::lock_guard<std::mutex> lock(gBundleRefMutex);
if (--bundleRefCount == 0) {
CFRelease((CFBundleRef)gBundleRef);
gBundleRef = nullptr;
}
}
} // namespace VSTGUI
#endif #endif

View file

@ -63,13 +63,27 @@ private:
#if LINUX #if LINUX
namespace VSTGUI namespace VSTGUI
{ {
void initializeSoHandle(); class SoHandleInitializer {
public:
SoHandleInitializer();
~SoHandleInitializer();
private:
SoHandleInitializer(const SoHandleInitializer&) = delete;
SoHandleInitializer& operator=(const SoHandleInitializer&) = delete;
};
} }
#endif #endif
#if MAC #if MAC
namespace VSTGUI namespace VSTGUI
{ {
void initializeBundleRef(); class BundleRefInitializer {
public:
BundleRefInitializer();
~BundleRefInitializer();
private:
BundleRefInitializer(const BundleRefInitializer&) = delete;
BundleRefInitializer& operator=(const BundleRefInitializer&) = delete;
};
} }
#endif #endif