From 65a375bfd9454efa5d10aa6ed9ebf0a7a6560afa Mon Sep 17 00:00:00 2001 From: Ansuman Sahoo Date: Mon, 11 May 2026 22:44:04 +0530 Subject: [PATCH] clean vsock sockets after krunkit exit Fixes #101 Signed-off-by: Ansuman Sahoo --- Cargo.lock | 56 +++++++++++++++++++++++++++++++++++++++++++++----- Cargo.toml | 1 + src/cleanup.rs | 40 ++++++++++++++++++++++++++++++++++++ src/context.rs | 19 ++++++++++++++++- src/main.rs | 5 +++++ 5 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 src/cleanup.rs diff --git a/Cargo.lock b/Cargo.lock index 655996b..271aa3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,7 +46,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -56,7 +56,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -107,6 +107,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "clap" version = "4.5.0" @@ -194,6 +200,17 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +[[package]] +name = "ctrlc" +version = "3.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +dependencies = [ + "dispatch2", + "nix 0.31.2", + "windows-sys 0.61.2", +] + [[package]] name = "dispatch2" version = "0.3.0" @@ -202,6 +219,7 @@ checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.10.0", "block2", + "libc", "objc2", ] @@ -271,6 +289,7 @@ dependencies = [ "anyhow", "clap", "core-foundation", + "ctrlc", "env_logger", "log", "mac_address", @@ -281,9 +300,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "log" @@ -297,7 +316,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4863ee94f19ed315bf3bc00299338d857d4b5bc856af375cc97d237382ad3856" dependencies = [ - "nix", + "nix 0.23.2", "winapi", ] @@ -329,6 +348,18 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nix" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "ntapi" version = "0.4.1" @@ -589,6 +620,12 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-result" version = "0.1.2" @@ -607,6 +644,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 244914e..bba3257 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,5 +16,6 @@ sysinfo = "0.31.4" log = "0.4.0" env_logger = "0.11.8" regex = "1.11.1" +ctrlc = "3.4" core-foundation = "0.10.1" objc2-io-kit = "0.3.2" diff --git a/src/cleanup.rs b/src/cleanup.rs new file mode 100644 index 0000000..6731324 --- /dev/null +++ b/src/cleanup.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 + +use std::path::PathBuf; +use std::sync::Arc; + +/// Remove each socket file, logging the outcome. Missing files are silently ignored. +fn remove_sockets(paths: &[PathBuf]) { + for path in paths { + match std::fs::remove_file(path) { + Ok(()) => log::info!("removed vsock socket: {}", path.display()), + Err(e) if e.kind() == std::io::ErrorKind::NotFound => {} + Err(e) => log::warn!("failed to remove vsock socket {}: {}", path.display(), e), + } + } +} + +/// Guard that cleans up vsock socket files when dropped (normal exit) and +/// also installs a Ctrl-C handler so the sockets are removed on SIGINT. +pub struct VsockCleanupGuard { + paths: Arc>, +} + +impl VsockCleanupGuard { + /// Create the guard **and** register the SIGINT handler. + pub fn new(paths: Vec) -> Result { + let paths = Arc::new(paths); + let handler_paths = Arc::clone(&paths); + ctrlc::set_handler(move || { + remove_sockets(&handler_paths); + std::process::exit(0); + })?; + Ok(Self { paths }) + } +} + +impl Drop for VsockCleanupGuard { + fn drop(&mut self) { + remove_sockets(&self.paths); + } +} diff --git a/src/context.rs b/src/context.rs index eed1a6e..696cf5a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -17,7 +17,7 @@ use std::{ }; use crate::timesync::timesync_listener; -use crate::virtio::{VsockAction, VsockConfig}; +use crate::virtio::{VirtioDeviceConfig, VsockAction, VsockConfig}; use anyhow::{anyhow, Context}; use env_logger::{Builder, Env, Target}; @@ -217,6 +217,23 @@ impl TryFrom for KrunContext { } impl KrunContext { + /// Collect all vsock socket paths that should be cleaned up on exit. + pub fn vsock_socket_paths(&self) -> Vec { + let mut paths = Vec::new(); + for device in &self.args.devices { + if let VirtioDeviceConfig::Vsock(vsock) = device { + paths.push(vsock.socket_url.clone()); + } + } + if self.args.timesync.is_some() { + paths.push(PathBuf::from(format!( + "/tmp/krunkit_timesync_{}.sock", + std::process::id() + ))); + } + paths + } + /// Spawn a thread to listen for shutdown requests and run the workload. If behaving properly, /// the main thread will never return from this function. pub fn run(&self) -> Result<(), anyhow::Error> { diff --git a/src/main.rs b/src/main.rs index 96e3170..79a509f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,12 +2,14 @@ #![allow(dead_code)] +mod cleanup; mod cmdline; mod context; mod status; mod timesync; mod virtio; +use cleanup::VsockCleanupGuard; use cmdline::Args; use context::KrunContext; @@ -18,6 +20,9 @@ fn main() -> Result<(), anyhow::Error> { // accordingly. let ctx = KrunContext::try_from(Args::parse())?; + // The guard removes vsock socket files on drop (normal exit) and on Ctrl-C. + let _cleanup = VsockCleanupGuard::new(ctx.vsock_socket_paths())?; + // Run the workload. If behaving properly, the main thread will not return from this // function. ctx.run()?;