forked from unom/punktfunk
Patch 0009, reported, written and proven live by luxus (punktfunk-overlay#9): when the capture consumer leaves, stream_handle_remove_buffer — and the stale-push path in dispatch_nudge — destroyed idle buffers on the PipeWire thread. Dropping the last CVulkanTexture reference there calls into the Vulkan driver (vkDestroyImage / FreeMemory / dmabuf fds) while steamcompmgr can still be inside vulkan_screenshot on another buffer of the same 4-buffer pool; on NVIDIA the race lands as a SIGSEGV in CVulkanCmdBuffer::insertBarrier. The timing is what made it selectively lethal: it fires at stream END — exactly the window where the host keeps the headless display lingering for a reconnect. So the kept display was already dead (journal: linger line → coredump → "kept display was dead — recreating") and the "resumed" session was a fresh compositor with the game lost. The fix queues the corpses (bury_buffer, mutex-guarded) and steamcompmgr reaps them on every vblank, including while the stream is only paused — the linger state itself. Field-proven on the reporter's NVIDIA host: 4 coredumps in one evening of BG3 at 4K60 HDR with --pipewire-composite- cursor (the heaviest paint path we ship), zero after; disconnect/reconnect confirmed live to reuse the lingered session (2026-08-13). Three of the four stacks are this race; the fourth (~CVulkanDevice during exit) is patch 0006's already-fixed static-destruction bug — do not re-diagnose it as part of this. Ours differs from the overlay's original only by the meson.build banner hunk: +pfhdr6 → +pfhdr7, PKGBUILD 3.16.25.pfhdr7-1. No new capability — same rule as pfhdr5/6: "reconnect lost my game" triage has to read a box's exposure off its banner, and every probe is >=. Known residual, deliberately untouched: add_buffer's error path still deletes on the PW thread. By the later `goto error`s a texture may be attached, so the race is reachable there in theory — but only when an add FAILS mid-renegotiation, which no field coredump shows; the patch stays byte-identical with what was proven on-glass. Verified: the full 0001..0009 series applies onto the bare 5fb8dce4 pin with plain `git am` (the build script's own invocation, no -3, no fuzz) and with `git am -3`; the fc44 CI image (punktfunk-fedora44-rpm) builds the result with rpm.yml's exact dep recipe to a binary whose banner reads `3.16.25-20-g40fe8b5+pfhdr7 (gcc 16.1.1)`. After 0009, destroy_buffer has exactly two callers left — pipewire_reap_dead_buffers (steamcompmgr vblank) and pipewire_destroy_buffer (steamcompmgr's copy-completion path) — both on the compositor thread. Nix, deb, sysext and rpm all glob patches/*.patch and read the level off the banner, so no other packaging file moves.