Three unwind holes in the EGL side, all of the same shape — fallible
construction over raw handles with no Drop to unwind through — and all
retried per frame, so a sustained failure (VRAM pressure is the realistic
one) leaked unboundedly:
- The GlBlit/Nv12Blit/Yuv444Blit constructors interleave GL-object creation
with fallible steps (FBO completeness, CUDA registration, pool
allocation). A GlNameGuard now owns every bare GL name until the final
struct exists; on unwind it deletes them AFTER the RegisteredTexture
locals unregister (declaration order), preserving the
unregister-before-delete invariant. gl.rs gets the same treatment for its
compile paths: the vertex shader on a fragment-compile failure, the
program on a link failure. (R1)
- EglImporter::new leaked the DRM render-node fd and the whole gbm_device on
every '?' after their creation (most realistically cuda::context() failing
on a host where EGL comes up but CUDA does not). Both now live in a
GbmDevice with its own Drop: destroy the device, then close the fd. (R2)
- EglImporter's manual Drop destroyed the gbm device and closed the fd
BEFORE field drops ran the blit destructors, which then called
cuGraphicsUnregisterResource/glDeleteTextures against a dead native
display — the stale-driver-state class this path once crashed on. The
Drop impl is gone; teardown is now purely field order (blits and bridge
first, GbmDevice last), and the blit SAFETY comments cite that order
instead of the previously-false claim. (R4)
(R1/R2/R4 from design/pf-zerocopy-sweep-handoff.md.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>