Description
The virtiofsd process is spawned as a fire-and-forget child in pkg/unikontainers/utils.go:206-217. Its PID is never stored, never reaped, and never killed. When the VMM (QEMU/Cloud-Hypervisor) exits, virtiofsd keeps running as an orphan, holding open the vhost-user socket and the shared directory mount.
On container restart, the old virtiofsd conflicts with the new one on the same socket path. Since cmd.Stdout = os.Stdout, virtiofsd output is mixed into the VMM's output. If virtiofsd crashes, there is no detection or recovery.
func spawnProcess(binaryPath string, args []string) error {
cmd := exec.Command(binaryPath, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return err
}
return nil // cmd.Process is never stored or waited on
}
System info
- Urunc version: current (main)
- Arch: all
- VMM: QEMU, Cloud-Hypervisor (virtiofs-based)
- Unikernel: any (virtiofs-based)
Steps to reproduce
- Start a virtiofs-based container (e.g., QEMU with virtiofs shared fs).
- Kill/stop the container.
- Check for orphaned virtiofsd processes:
ps aux | grep virtiofsd.
- Observe the orphan process holding the vhost-user socket.
- Attempt to restart the container - it fails with "socket already in use".
Description
The virtiofsd process is spawned as a fire-and-forget child in
pkg/unikontainers/utils.go:206-217. Its PID is never stored, never reaped, and never killed. When the VMM (QEMU/Cloud-Hypervisor) exits, virtiofsd keeps running as an orphan, holding open the vhost-user socket and the shared directory mount.On container restart, the old virtiofsd conflicts with the new one on the same socket path. Since
cmd.Stdout = os.Stdout, virtiofsd output is mixed into the VMM's output. If virtiofsd crashes, there is no detection or recovery.System info
Steps to reproduce
ps aux | grep virtiofsd.