#![deny(clippy::undocumented_unsafe_blocks)] never inspected the body of an
unsafe fn — operations there are not "unsafe blocks" — so roughly 20
functions' worth of raw GL/CUDA/Vulkan driver calls sat outside the
invariant the crate advertises. Concretely, that blind spot is why the
constructor-leak and teardown-ordering shapes fixed earlier in this series
could ship without ever prompting a reviewer.
#![deny(unsafe_op_in_unsafe_fn)] now closes the gap: every unsafe fn body
is an explicit unsafe block carrying a SAFETY comment that names the
caller contract it relies on (the dlopen'd CUDA wrapper table gets a
uniform forward-to-live-table proof). Mechanical; no behavior change.
(V2 from design/pf-zerocopy-sweep-handoff.md.)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
linux/zerocopy/* (CUDA context/buffers + EGL/Vulkan dmabuf import + the isolated
import worker) and linux/dmabuf_fence.rs move wholesale into crates/pf-zerocopy,
so the coming pf-frame vocabulary crate (FramePayload::Cuda owns a DeviceBuffer)
and the pf-encode/pf-capture subsystem crates can reach the GPU plumbing without
the host orchestrator in between (plan §W6). Content stays Linux-only; the crate
compiles to an empty lib elsewhere, so dependents carry a plain dependency.
drm_fourcc deliberately does NOT move: it consumes the frame vocabulary
(PixelFormat), which sits ABOVE pf-zerocopy — it lives with capture for now and
moves into pf-frame next. cuda's ffi re-export bumps pub(crate)->pub (the raw
CUdeviceptr vocabulary is consumed across the crate boundary by the encode
backends). A crate::zerocopy shim module keeps every existing path valid until
capture/encode themselves move out.
Verified: Linux clippy -D warnings (pf-zerocopy --all-targets + host
nvenc,vulkan-encode,pyrowave --all-targets) + 17/17 pf-zerocopy tests + 321/321
host tests; Windows clippy nvenc,amf-qsv --all-targets Finished exit 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>