qt: wake the renderer CV before ghostty_surface_free in dtor
If the renderer thread is parked in presentVulkanDmabuf's
condition_variable wait (added in f48465cda) when GhosttySurface
is destroyed, ghostty_surface_free's per-surface tear-down race
with our mutex/CV destruction once the dtor body returns —
manifests as a SEGV (address boundary error) when fish kills the
parent shell and the surface dtors fan out faster than the
renderer can wake from its 100 ms timeout.
Set m_hidden=true + notify_all the compositor CV BEFORE handing
the surface to libghostty for tear-down. The renderer wakes
immediately, sees m_hidden, bails without parking, returns to
the xev loop, and libghostty's shutdown path joins the thread
cleanly while our mutex/CV are still alive.
Same pattern as the Hide / PlatformSurface destroy handlers
(which already notify_all for the same reason).
Co-Authored-By: claude-flow <ruv@ruv.net>
pull/12846/head
parent
f48465cda5
commit
dab2a1930c
|
|
@ -214,6 +214,22 @@ GhosttySurface::~GhosttySurface() {
|
|||
// QPointer auto-nulls on a destroyed QObject, so .data() is safe.
|
||||
delete m_inspectorWindow.data();
|
||||
|
||||
// Wake the renderer thread if it's parked in presentVulkanDmabuf's
|
||||
// CV wait BEFORE we hand the surface to libghostty for teardown.
|
||||
// ghostty_surface_free below shuts down + joins the renderer
|
||||
// thread; if that thread is blocked on our CV, the join either
|
||||
// hangs for our 100 ms timeout (best case) or races our mutex /
|
||||
// CV destruction once this body returns (worst case → SEGV when
|
||||
// the renderer wakes from the timeout and touches the destroyed
|
||||
// mutex). The predicate also checks m_hidden so the renderer
|
||||
// bails out without parking another frame.
|
||||
m_hidden.store(true, std::memory_order_release);
|
||||
{
|
||||
std::lock_guard<std::mutex> lg(m_compositorMutex);
|
||||
m_compositorReady = true;
|
||||
}
|
||||
m_compositorCv.notify_all();
|
||||
|
||||
// GL teardown must happen with the context current. If makeCurrent
|
||||
// fails (e.g. the ctor failed before m_context could be created), we
|
||||
// still free m_surface — it carries no GL state of its own — and we
|
||||
|
|
|
|||
Loading…
Reference in New Issue