Found in a wider bug audit of the streaming/process-management code.
- Viewer ctrl-c/SIGINT was ignored mid-stream: viewer::run raced the
cancel token only against listener.accept(), not the bridge itself, so
once the local player connected nothing checked it. CLI needed a second
ctrl-c to quit and a GUI "Disconnect" only took effect via the child's 2s
SIGKILL backstop (and the host saw the viewer ~2s longer). Now races the
bridge against cancel, mirroring the host's handle_peer. (viewer/mod.rs)
- Wayland portal pipewire fd leaked on a capture-setup error: wayland::start
into_raw_fd'd the fd and relied on pipeline::spawn's after_spawn hook to
close it, but setup_audio/gst-spawn can ?-return before the hook runs,
leaking the fd per failed attempt. Now the OwnedFd is moved into the hook,
so it's closed whether the hook runs or (on early error) the unused closure
is dropped. (host/wayland.rs)
- Detached players (mpv/vlc) zombied under the long-lived GUI: spawn_detached
dropped the std Child, which has no orphan reaping, so each closed player
left a <defunct> entry until the GUI exited. Now a detached thread wait()s
it; the setsid'd player still survives a parent exit (init reaps it then).
A double-fork was avoided deliberately — fork(2) + non-trivial work in this
multithreaded process is unsound. (common/process.rs)
47 gui / 8 headless tests pass, clippy + fmt clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bare `pixelpass` now opens a dialoguer-driven Host/View menu instead of
going straight to host mode. Host path copies the ticket to the system
clipboard via arboard with silent print-only fallback. View path
prompts for the ticket, then after the local listener binds prompts
mpv-vs-VLC and spawns it detached (setsid + null stdio) so the player
survives pixelpass exiting.
Headless invocations (`pixelpass <ticket>`, `pixelpass --repair`)
unchanged. Per spec at ~/Documents/pixelpass-interactive-mode-spec.md.