From 3a4b2049f145b3bfe28e863223b98ee5f5f8e601 Mon Sep 17 00:00:00 2001 From: madah81pnz1 <52885812+madah81pnz1@users.noreply.github.com> Date: Thu, 9 Jan 2025 03:27:53 +0100 Subject: [PATCH] Fix crash when repeatedly opening/closing GUI Cairo keeps a global cache list of connections, but since the reference count of the device never reaches 0, the devices are never removed from this cache list. The crash happens when a new xcb_connection is made, and the new pointer happens to be the same as an existing pointer in this cache list, then the wrong cairo_xcb_connection is returned. Then no screen can be found, since the root is not the same for that old xcb_connection and the new one. Thus we end up at ASSERT_NOT_REACHED in _get_screen_index(), in cairo-xcb-screen.c Note that there is some resource leakage somewhere, since the reference count of the cairo devices should reach 0 at some point, but never do. Fixes #334 --- vstgui/lib/platform/linux/cairographicscontext.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/vstgui/lib/platform/linux/cairographicscontext.cpp b/vstgui/lib/platform/linux/cairographicscontext.cpp index ed7e493fd..3ee6f8a83 100644 --- a/vstgui/lib/platform/linux/cairographicscontext.cpp +++ b/vstgui/lib/platform/linux/cairographicscontext.cpp @@ -43,6 +43,20 @@ inline cairo_matrix_t convert (const TransformMatrix& ct) struct CairoGraphicsDeviceFactory::Impl { std::vector> devices; + Impl() = default; + ~Impl() noexcept + { + for (auto& device : devices) + { +#if DEBUG + DebugPrint ("Cairo device reference count: %u\n", cairo_device_get_reference_count (device->get ())); +#endif + // Force cairo to remove this device from its internal cache list of devices. + // This is only needed because the reference count never seem to reach 0, + // which means there is still some resource leakage elsewhere in the code. + cairo_device_finish (device->get ()); + } + } }; //-----------------------------------------------------------------------------