From 174194ebd2df2795b516bee906b04efe0c5f59bc Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Fri, 4 Sep 2020 10:30:03 +0200 Subject: [PATCH] Fix a plugin crash on closing UI --- lv2/sfizz_ui.cpp | 13 +++--- lv2/vstgui_helpers.cpp | 90 +++++++++++++++++++----------------------- lv2/vstgui_helpers.h | 18 ++++++++- 3 files changed, 63 insertions(+), 58 deletions(-) diff --git a/lv2/sfizz_ui.cpp b/lv2/sfizz_ui.cpp index 020f5989..10ed2cbe 100644 --- a/lv2/sfizz_ui.cpp +++ b/lv2/sfizz_ui.cpp @@ -74,6 +74,12 @@ typedef std::unique_ptr FrameHolder; /// struct sfizz_ui_t : EditorController, VSTGUIEditorInterface { +#if LINUX + SoHandleInitializer soHandleInitializer; +#endif +#if MAC + BundleRefInitializer bundleRefInitializer; +#endif LV2UI_Write_Function write = nullptr; LV2UI_Controller con = nullptr; LV2_URID_Map *map = nullptr; @@ -369,13 +375,6 @@ LV2_SYMBOL_EXPORT const LV2UI_Descriptor * lv2ui_descriptor(uint32_t index) { -#if LINUX - VSTGUI::initializeSoHandle(); -#endif -#if MAC - VSTGUI::initializeBundleRef(); -#endif - switch (index) { case 0: diff --git a/lv2/vstgui_helpers.cpp b/lv2/vstgui_helpers.cpp index d1ad3187..0a402a20 100644 --- a/lv2/vstgui_helpers.cpp +++ b/lv2/vstgui_helpers.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #if LINUX #include #include @@ -143,36 +144,31 @@ namespace VSTGUI { void* soHandle = nullptr; -static volatile bool soHandleInitialized = false; +static volatile size_t soHandleCount = 0; static std::mutex soHandleMutex; -struct Dl_handle_deleter +SoHandleInitializer::SoHandleInitializer() { - void operator()(void* x) const noexcept - { - dlclose(x); - } -}; -static std::unique_ptr soHandlePointer; -} // namespace VSTGUI - -void VSTGUI::initializeSoHandle() -{ - if (VSTGUI::soHandleInitialized) - return; - - std::lock_guard 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; + std::lock_guard lock(soHandleMutex); + if (soHandleCount++ == 0) { + Dl_info info; + if (dladdr((void*)&lv2ui_descriptor, &info)) + soHandle = dlopen(info.dli_fname, RTLD_LAZY); + if (!soHandle) + throw std::runtime_error("SoHandleInitializer"); + } } + +SoHandleInitializer::~SoHandleInitializer() +{ + std::lock_guard lock(soHandleMutex); + if (--soHandleCount == 0) { + dlclose(soHandle); + soHandle = nullptr; + } +} + +} // namespace VSTGUI #endif /// @@ -194,31 +190,27 @@ namespace VSTGUI { void* gBundleRef = nullptr; -static volatile bool gBundleRefInitialized = false; +static volatile size_t gBundleRefCount = 0; static std::mutex gBundleRefMutex; -struct CFBundle_deleter { - void operator()(CFBundleRef x) const noexcept - { - CFRelease(x); - } -}; -static std::unique_ptr<__CFBundle, CFBundle_deleter> gBundleRefPointer; -} // namespace VSTGUI - -void VSTGUI::initializeBundleRef() +BundleRefInitializer::BundleRefInitializer() { - if (VSTGUI::gBundleRefInitialized) - return; - - std::lock_guard lock(VSTGUI::gBundleRefMutex); - if (VSTGUI::gBundleRefInitialized) - return; - - CFBundleRef bundleRef = GetPluginBundle(); - VSTGUI::gBundleRef = bundleRef; - VSTGUI::gBundleRefPointer.reset(bundleRef); - - VSTGUI::gBundleRefInitialized = true; + std::lock_guard lock(gBundleRefMutex); + if (bundleRefCount++ == 0) { + gBundleRef = GetPluginBundle(); + if (!gBundleRef) + throw std::runtime_error("BundleRefInitializer"); + } } + +BundleRefInitializer::~BundleRefInitializer() +{ + std::lock_guard lock(gBundleRefMutex); + if (--bundleRefCount == 0) { + CFRelease((CFBundleRef)gBundleRef); + gBundleRef = nullptr; + } +} + +} // namespace VSTGUI #endif diff --git a/lv2/vstgui_helpers.h b/lv2/vstgui_helpers.h index 8367a2c4..2fbcd841 100644 --- a/lv2/vstgui_helpers.h +++ b/lv2/vstgui_helpers.h @@ -63,13 +63,27 @@ private: #if LINUX namespace VSTGUI { -void initializeSoHandle(); +class SoHandleInitializer { +public: + SoHandleInitializer(); + ~SoHandleInitializer(); +private: + SoHandleInitializer(const SoHandleInitializer&) = delete; + SoHandleInitializer& operator=(const SoHandleInitializer&) = delete; +}; } #endif #if MAC namespace VSTGUI { -void initializeBundleRef(); +class BundleRefInitializer { +public: + BundleRefInitializer(); + ~BundleRefInitializer(); +private: + BundleRefInitializer(const BundleRefInitializer&) = delete; + BundleRefInitializer& operator=(const BundleRefInitializer&) = delete; +}; } #endif