1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-09 23:34:20 +00:00

WebBrowserComponent: Fix bug where Linux browser process could segfault during shutdown

This issue could be observed when loading the WebViewPluginDemo in the
AudioPluginHost, opening its editor, and then attempting to close the
editor window using the titlebar button. Tested on Fedora 42 with
libwebkit2gtk-4.1.

Unloading the webkit library with dlclose seems to cause the webview
process to crash, even if gtk_main() has already exited at that point.

Maybe this points to a need to manually clean up the webview somehow
before calling gtk_main_quit, but I can't see any obvious candidate
functions in the docs (gtk_widget_destroy doesn't seem to help).

The workaround presented here just opens the webkit library with
RTLD_NODELETE, which isn't ideal but might be necessary if this library
hasn't been designed with dynamic load/unload in mind.
This commit is contained in:
reuk 2025-11-06 17:02:44 +00:00
parent 3b569d5801
commit 14ee9e46ff
No known key found for this signature in database

View file

@ -264,6 +264,44 @@ public:
JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL_INLINE (WebKitSymbols)
private:
struct DylibHandle
{
DylibHandle() = default;
explicit DylibHandle (const char* str)
: DylibHandle (str, RTLD_NOW | RTLD_LOCAL) {}
DylibHandle (const char* str, int flags)
: handle (dlopen (str, flags)) {}
~DylibHandle()
{
if (handle != nullptr)
dlclose (handle);
}
DylibHandle (DylibHandle&& other) noexcept
: handle (std::exchange (other.handle, nullptr)) {}
DylibHandle& operator= (DylibHandle&& other) noexcept
{
auto local = std::move (other);
std::swap (local.handle, handle);
return *this;
}
void* getFunction (const char* name) const
{
jassert (handle != nullptr);
return dlsym (handle, name);
}
explicit operator bool() const { return handle != nullptr; }
private:
void* handle = nullptr;
};
WebKitSymbols() = default;
~WebKitSymbols()
@ -285,7 +323,7 @@ private:
}
template <typename FuncPtr>
bool loadSymbols (DynamicLibrary& lib, SymbolBinding<FuncPtr> binding)
bool loadSymbols (DylibHandle& lib, SymbolBinding<FuncPtr> binding)
{
if (auto* func = lib.getFunction (binding.name))
{
@ -297,7 +335,7 @@ private:
}
template <typename FuncPtr, typename... Args>
bool loadSymbols (DynamicLibrary& lib, SymbolBinding<FuncPtr> binding, Args... args)
bool loadSymbols (DylibHandle& lib, SymbolBinding<FuncPtr> binding, Args... args)
{
return loadSymbols (lib, binding) && loadSymbols (lib, args...);
}
@ -395,20 +433,24 @@ private:
bool openWebKitAndDependencyLibraries (const WebKitAndDependencyLibraryNames& names)
{
if (webkitLib.open (names.webkitLib) && jsLib.open (names.jsLib) && soupLib.open (names.soupLib))
if ( (webkitLib = DylibHandle (names.webkitLib, RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE))
&& (jsLib = DylibHandle (names.jsLib))
&& (soupLib = DylibHandle (names.soupLib)))
{
return true;
}
for (auto* l : { &webkitLib, &jsLib, &soupLib })
l->close();
*l = {};
return false;
}
//==============================================================================
DynamicLibrary webkitLib, jsLib, soupLib;
DylibHandle webkitLib, jsLib, soupLib;
DynamicLibrary gtkLib { "libgtk-3.so" },
glib { "libglib-2.0.so" };
DylibHandle gtkLib { "libgtk-3.so" },
glib { "libglib-2.0.so" };
const bool webKitIsAvailable = ( openWebKitAndDependencyLibraries ({ "libwebkit2gtk-4.1.so",
"libjavascriptcoregtk-4.1.so",