vtkXOpenGLRenderWindow::DestroyWindow() can deadlock when Finalize() runs from QVTKRenderWindowInteractor.closeEvent()

We meet an intermittent SIGSEGV on closing a Qt window that embeds `QVTKRenderWindowInteractor`. Confirmed via a core-dump backtrace and by reading `vtkXOpenGLRenderWindow`: the vendored interactor only finalizes its render window through a fallback wired to the parent’s `destroyed` signal, which fires from `~QObject()` – i.e. *after* `~QWidget()` has already torn down the native X11 window. By the time that fallback runs, `MakeCurrent()` calls `glXMakeCurrent(DisplayId, WindowId, ContextId)` against an already-destroyed drawable,

As a workaround, we tried calling `render_window.Finalize()` ourselves, explicitly, early in `closeEvent()`, before Qt’s native teardown runs. That stopped the crash — but it surfaced a new **hang instead**. Live debugging gdb shows this is a genuine deadlock between our GUI thread inside `vtkXOpenGLRenderWindow::DestroyWindow()` (called from our early `Finalize()`) and a driver-internal thread NVIDIA’s GLX implementation spawns for Present/vsync bookkeeping.

## Environment

- VTK 9.6.2 (Python wheel, `vtkmodules`), locally repackaged but as far as we can tell unmodified in `Rendering/OpenGL2` and the vendored Qt interactor — we could read the installed `QVTKRenderWindowInteractor.py` directly and it matches stock upstream in the relevant closeEvent/Finalize path.

- Python 3.8, PySide2 (Qt 5)

- Ubuntu 22.04, X11 (not Wayland), kernel 6.8 (real-time variant)

- NVIDIA RTX 2000 Ada Generation, proprietary driver **595.71.05**, CUDA 13.2

- Rendering is on-screen, single `vtkRenderWindow` with two layered `vtkRenderer`s, HDRI/PBR lighting + a tone-mapping pass, embedded via `QVTKRenderWindowInteractor` in a normal (non-Xvfb) desktop session.

## Symptom 1 (worked around): intermittent SIGSEGV on close

Root cause, confirmed via a core-dump backtrace and by reading `vtkXOpenGLRenderWindow`: the vendored `QVTKRenderWindowInteractor` only finalizes its render window via the fallback wired to its **parent’s** `destroyed` signal, which fires from `~QObject()` — i.e. *after* `~QWidget()` has already torn down the native X11 window. `MakeCurrent()` then calls `glXMakeCurrent(DisplayId, WindowId, ContextId)` against an already-destroyed drawable with no validity check on `WindowId` — a use-after-free that segfaults under the NVIDIA driver.

**Workaround we tried:** call `render_window.Finalize()` ourselves, explicitly, early in our widget’s `closeEvent()` — before `super().closeEvent()` runs and before Qt schedules `deleteLater()`/`deleteChildren()`. This reliably stopped the crash.

## Symptom 2 (new, unresolved): intermittent hang on close, after that workaround

Since applying that workaround, closing the same window sometimes hangs instead of crashing — completely unresponsive, no crash, requiring the desktop’s “application not responding — Force Quit” path (i.e. `SIGKILL`) to recover.

## Some Questions

1. Has anyone seen `DestroyWindow()`/`Finalize()` hang (not crash) specifically inside `libnvidia-glcore.so` / `libGLX_nvidia.so`, with a driver-spawned thread stuck in `xcb_wait_for_special_event()`?

2. Is this the same underlying issue as #18637, just manifesting as a hang instead of a block-forever-but-still-“running” state, or a different bug in the same neighborhood?

3. Is there a documented-safe way to ensure no GPU work/Present is in flight before calling `Finalize()`/`DestroyWindow()` (an explicit “wait for idle” that’s safer than `glFinish()`'s own internal behavior seems to be here), so downstream users don’t have to manually track and stop every possible renderer themselves?

4. Should `vtkXOpenGLRenderWindow`'s Qt-embedding docs call out a stronger thread-safety/timing contract for `Finalize()` given it can apparently deadlock against the vendor driver’s own threads?