round 15: log instead of silently dropping errors in greeter/netctl/hotplugd

Round 15 audit cleanup. Three production paths were discarding
process / filesystem errors via bare 'let _ = ...'. Each silently
swallowed the error and the caller had no way to know the cleanup
failed — leading to zombie children (greeter), stale active-profile
symlinks (netctl), or unreaped USB device drivers (hotplugd).

1. local/recipes/system/redbear-greeter/source/src/main.rs — the
   kill_child() helper now logs on kill() and wait() failure (with
   debug-level success log) instead of 'let _ = process.kill();
   let _ = process.wait();'. A failing kill() now produces an
   eprintln so the operator sees it; wait() outcome is logged
   at debug level.

2. local/recipes/system/redbear-netctl/source/src/main.rs — both
   'let _ = fs::remove_file(active_profile_path());' sites (line 201
   in stop_profile and line 224 in disable_profile) now log on
   failure via eprintln. A failed remove_file previously left a
   dangling 'active' symlink that subsequent boot would re-activate
   silently.

3. local/recipes/system/redbear-usb-hotplugd/source/src/main.rs —
   the 'if let Some(ref mut child) = dev.child { let _ = child.kill(); }'
   in the disconnect path now logs on kill() failure (log::warn) so
   a leaked USB driver child produces a visible warning.

Found by the Round 14 audit (local/docs/3D-DESKTOP-COMPREHENSIVE-PLAN.md §10).
This commit is contained in:
2026-07-27 21:43:33 +09:00
parent 8fbc113d9f
commit 5682072e58
3 changed files with 18 additions and 5 deletions
@@ -323,8 +323,13 @@ impl GreeterDaemon {
fn kill_child(child: &mut Option<Child>) {
if let Some(process) = child.as_mut() {
let _ = process.kill();
let _ = process.wait();
if let Err(e) = process.kill() {
eprintln!("redbear-greeterd: kill failed: {e}");
}
match process.wait() {
Ok(status) => log::debug!("redbear-greeterd: child exited with {status}"),
Err(e) => eprintln!("redbear-greeterd: wait failed: {e}"),
}
}
*child = None;
}
@@ -198,7 +198,9 @@ fn stop_profile(name: &str) -> Result<(), String> {
}
}
if active_profile_name()?.as_deref() == Some(name) {
let _ = fs::remove_file(active_profile_path());
if let Err(e) = fs::remove_file(active_profile_path()) {
eprintln!("netctl: failed to remove active profile link: {e}");
}
}
println!("stopped {}", name);
Ok(())
@@ -221,7 +223,9 @@ fn disable_profile(profile: Option<&str>) -> Result<(), String> {
}
}
let _ = fs::remove_file(active_profile_path());
if let Err(e) = fs::remove_file(active_profile_path()) {
eprintln!("netctl: failed to remove active profile link: {e}");
}
println!("disabled {}", profile.unwrap_or("active"));
Ok(())
}
@@ -251,7 +251,11 @@ fn main() {
}
if !connected {
log::info!("port {}: device disconnected", port_path);
if let Some(ref mut child) = dev.child { let _ = child.kill(); }
if let Some(ref mut child) = dev.child {
if let Err(e) = child.kill() {
log::warn!("port {}: kill failed: {e}", port_path);
}
}
dev.child = None;
dev.state = PortState::Disconnected;
}