From 1268539b26b42c45af4f591902f429a91dca00fb Mon Sep 17 00:00:00 2001 From: Nguyen Dinh Phi Date: Wed, 8 Apr 2026 23:11:27 +0800 Subject: [PATCH] main: remove api socket path when start_vmm fails Previously the UNIX socket file was only removed on the success path (start_vmm returned Ok(Some(path))). If start_vmm failed after the HTTP API had bound a path-based socket, the file could be left on disk. Parse --api-socket in parse_api_socket(), call start_vmm with the result, then unlink the path in main after start_vmm returns for both success and failure (fd= mode unchanged: no path to remove). Signed-off-by: Nguyen Dinh Phi --- cloud-hypervisor/src/main.rs | 80 ++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 31 deletions(-) diff --git a/cloud-hypervisor/src/main.rs b/cloud-hypervisor/src/main.rs index 415e7ed92..06ef1fe30 100644 --- a/cloud-hypervisor/src/main.rs +++ b/cloud-hypervisor/src/main.rs @@ -504,7 +504,37 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String .args(args) } -fn start_vmm(cmd_arguments: &ArgMatches) -> Result, Error> { +fn parse_api_socket(cmd_arguments: &ArgMatches) -> Result<(Option, Option), Error> { + if let Some(socket_config) = cmd_arguments.get_one::("api-socket") { + let mut parser = OptionParser::new(); + parser.add("path").add("fd"); + parser.parse(socket_config).unwrap_or_default(); + + if let Some(fd) = parser.get("fd") { + Ok(( + None, + Some(fd.parse::().map_err(Error::ParsingApiSocket)?), + )) + } else if let Some(path) = parser.get("path") { + Ok((Some(path), None)) + } else { + Ok(( + cmd_arguments + .get_one::("api-socket") + .map(|s| s.to_string()), + None, + )) + } + } else { + Ok((None, None)) + } +} + +fn start_vmm( + cmd_arguments: &ArgMatches, + api_socket_path: &Option, + api_socket_fd: Option, +) -> Result<(), Error> { let log_level = match cmd_arguments.get_count("v") { 0 => LevelFilter::Warn, 1 => LevelFilter::Info, @@ -527,31 +557,6 @@ fn start_vmm(cmd_arguments: &ArgMatches) -> Result, Error> { .map(|()| log::set_max_level(log_level)) .map_err(Error::LoggerSetup)?; - let (api_socket_path, api_socket_fd) = - if let Some(socket_config) = cmd_arguments.get_one::("api-socket") { - let mut parser = OptionParser::new(); - parser.add("path").add("fd"); - parser.parse(socket_config).unwrap_or_default(); - - if let Some(fd) = parser.get("fd") { - ( - None, - Some(fd.parse::().map_err(Error::ParsingApiSocket)?), - ) - } else if let Some(path) = parser.get("path") { - (Some(path), None) - } else { - ( - cmd_arguments - .get_one::("api-socket") - .map(|s| s.to_string()), - None, - ) - } - } else { - (None, None) - }; - let (api_request_sender, api_request_receiver) = channel(); let api_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::CreateApiEventFd)?; @@ -712,7 +717,7 @@ fn start_vmm(cmd_arguments: &ArgMatches) -> Result, Error> { let vmm_thread_handle = vmm::start_vmm_thread( vmm::VmmVersionInfo::new(env!("BUILD_VERSION"), env!("CARGO_PKG_VERSION")), - &api_socket_path, + api_socket_path, api_socket_fd, #[cfg(feature = "dbus_api")] dbus_options, @@ -798,7 +803,7 @@ fn start_vmm(cmd_arguments: &ArgMatches) -> Result, Error> { dbus_api_graceful_shutdown(chs); } - r.map(|_| api_socket_path) + r } // This is a best-effort solution to the latency induced by the RCU @@ -904,9 +909,22 @@ fn main() { warn!("Error expanding FD table: {e}"); } - let exit_code = match start_vmm(&cmd_arguments) { - Ok(path) => { - path.map(|s| std::fs::remove_file(s).ok()); + let (api_socket_path, api_socket_fd) = match parse_api_socket(&cmd_arguments) { + Ok(p) => p, + Err(top_error) => { + cloud_hypervisor::cli_print_error_chain(&top_error, "Cloud Hypervisor", |_, _, _| None); + std::process::exit(1); + } + }; + + let vmm_result = start_vmm(&cmd_arguments, &api_socket_path, api_socket_fd); + + if let Some(ref p) = api_socket_path { + let _ = std::fs::remove_file(p); + } + + let exit_code = match vmm_result { + Ok(()) => { info!("Cloud Hypervisor exited successfully"); 0 }