core/teardown: ask pixelpass to stop before killing it
The peerspeak half of phase 0c (design v3.4 §7.4 item 1). Stop Share and session teardown both went straight to `Child::kill()`, i.e. SIGKILL, which skips pixelpass's own cleanup and leaks one null-sink module every time. `ReapOnDrop::shutdown` now asks first: SIGINT, a bounded 2 s wait, then SIGKILL only if the child ignored the request. SIGINT specifically, not SIGTERM — pixelpass installs only a `ctrl_c()` handler, so SIGTERM would take the default disposition and be indistinguishable from SIGKILL. Signalling by pid is safe against pid reuse here: we have not reaped the child, so it is a zombie whose pid the kernel reserves until we wait it, and the pid cannot name a stranger. (Same reasoning that dismissed pixelpass bug #6.) The grace is 2 s because it is awaited inline in the core command loop, so it is also how long a wedged child can delay other commands. A healthy pixelpass never spends it. The drop/unwind path deliberately stays a hard kill: `Drop` cannot await, and there the ordering invariant (§7.1) outranks tidiness. Once the pixelpass half of 0c lands, the capture sink is connection-owned and that path stops leaking by construction. `libc` becomes a direct unix-only dependency, pinned to 0.2.186 — the version already in the tree via alsa/cpal/tokio — so Cargo.lock gains one line and no new code enters the build. Mutation-verified, five mutations, each killing its own gate: no wait (6 fail), reversed field order (2, reap test green), no reap loop (2, ordering test green), no SIGINT (6), no SIGKILL fallback (exactly 1 — the wedged-child test). 633 lib tests, clippy clean, fmt clean. Not yet field-tested: the live Stop Share gate (SIGINT sent, child exits within the bound, no fallback kill on the normal path) still owes a real run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -109,3 +109,10 @@ windows-sys = { version = "0.61", features = [
|
||||
"Win32_System_Diagnostics_ToolHelp",
|
||||
"Win32_System_Threading",
|
||||
] }
|
||||
|
||||
# Unix-only. Used for exactly one thing: sending SIGINT to our own
|
||||
# pixelpass child so it can run its cleanup before we resort to SIGKILL
|
||||
# (src/core/teardown.rs). Already in the tree via alsa/cpal/tokio, so
|
||||
# declaring it directly adds no new code to the build.
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2.186"
|
||||
|
||||
Reference in New Issue
Block a user