-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Linux] Repeatedly reopening GUI crashes host, asserts in cairo-xcb-screen.c #334
Comments
I did some troubleshooting and I think I've figured out what's going on. _cairo_xcb_connection_get() in cairo-xcb-connection.c uses a global connection cache, static cairo_list_t connections. _device_finish() in cairo-xcb-connection.c is the function that would have removed the connection from this global cache. I printed the refcount from CairoGraphicsDevice() and ~CairoGraphicsDevice(), using cairo_device_get_reference_count(impl->device). The value seems to never reach 0. Before commit a8b5c81, ~DrawHandler() used to have a call to cairo_device_finish(). This worked as in didn't crash, but only because it would forcefully remove and cleanup the cairo device. But then there are still ~10 other places that holds a reference count to it from somewhere. This is the main bug, a resource leak. CairoGraphicsDeviceFactory is deleted from VSTGUI::exit() via exitPlatform(). If VSTGUI::exit() is not called, the existing device would have been found and reused by the factory, which also holds a cache of devices. A fix is then to call cairo_device_finish() on each device in the CairoGraphicsDeviceFactory::Impl destructor:
Even if it is somewhat hacky fix, when the factory is deleted, the user has anyway called VSTGUI::exit(). So at that point, cairo should also be cleaned up. |
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 steinbergmedia#334
This looks to be the same as #249 but since that one was closed with a fix, I created this new issue, since there might not be the same root cause, even if it crashes at the same assert.
If I have a single plugin instance open with GUI, repeatedly clicking the UI button in Reaper will eventually lead to a crash, after about 2-3 times.
If I have two plugin instances open, both with their GUI open, it never crashes as long as at least one has their GUI open.
In my plugin, when the last GUI is closed, after the frame is deleted, I call VSTGUI::X11::RunLoop::exit() and then VSTGUI::exit().
The crash happens the next time GUI is created and opened again, as then Cairo doesn't seem to find any screens(?)
For debug builds of my plugin, it takes much longer time to trigger the crash, so I suspect there is some race condition when Cairo is uninitialized.
As a workaround, I changed so that RunLoop::exit() and VSTGUI::exit() are never called my plugin, which seems to solve the crashing problem. But then it might leak some resources instead, so not a good long term solution.
Reaper 7.29
Debian 12 Testing(Trixie)
Latest VSTGUI from git develop branch:
Stacktrace from gdb:
For reference, similar issue with Cairo:
https://cairo.cairographics.narkive.com/eXgzeIgH/concerns-regarding-xcb-backend
The text was updated successfully, but these errors were encountered: