vmm: clean up a stale API socket under a lock before bind

When Cloud Hypervisor crashed or was killed, the API socket file was
left on disk, so the next start failed with EADDRINUSE ("Address already
in use") and the VMM could not restart. This affects any environment
where the socket directory survives across restarts (systemd services,
Kubernetes emptyDir volumes, and so on).

Before binding the path-based API socket, take an exclusive lock on a
sidecar "<socket>.lock" file using the block crate's OFD-lock helper.
Holding it proves no other instance is bound to this path, so a stale
socket left by a crashed run can be removed safely and race-free. If
the lock is already held, fail with a clear "API socket is already in
use" error instead of clobbering the live instance. The lock is held
for the process lifetime and released by the kernel on exit or crash.
The fd-based (socket-activation) path is left unchanged.

This implements the lock-file approach suggested by @DemiMarie.

Fixes: #7784

Signed-off-by: Max Makarov <maxpain@linux.com>
Assisted-by: Claude:claude-opus-4-8 [Claude Code]
This commit is contained in:
Max Makarov
2026-06-03 13:11:56 +00:00
committed by Rob Bradford
parent 6219613bce
commit 0a08f6551a
2 changed files with 41 additions and 2 deletions
+4
View File
@@ -201,6 +201,10 @@ pub enum Error {
#[error("Error creation API server's socket")]
CreateApiServerSocket(#[source] io::Error),
/// The API server socket is already in use by another running instance
#[error("API socket {0:?} is already in use by another running instance")]
ApiSocketInUse(std::path::PathBuf),
#[cfg(feature = "guest_debug")]
#[error("Failed to start the GDB thread")]
GdbThreadSpawn(#[source] io::Error),