From 0e764b0571e06577523e3c41a6956b024e199473 Mon Sep 17 00:00:00 2001 From: Thales Maciel Date: Tue, 14 Apr 2026 19:53:26 -0300 Subject: [PATCH] Fix two daemon bugs: Firecracker context and sessionControllers init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vm.go: Firecracker was launched with context.Background() instead of the incoming request ctx. A cancelled or timed-out VM creation request could not stop mid-flight Firecracker process spawning, leaving an orphaned process and leaked resources. Replace the four firecrackerCtx uses with ctx directly; the local variable is removed. guest_sessions.go / daemon.go: sessionControllers map was lazily initialized with a nil-check inside every mutating method. With d.mu held this isn't a data race, but the pattern is fragile — any new method that writes to the map without copying the guard can panic. Initialize the map once in Open() alongside the other daemon maps and channels, and remove the redundant nil-checks from setGuestSessionController and claimGuestSessionController. --- internal/daemon/daemon.go | 15 ++++++++------- internal/daemon/guest_sessions.go | 6 ------ internal/daemon/vm.go | 9 ++++----- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 0658107..017ea2b 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -80,13 +80,14 @@ func Open(ctx context.Context) (d *Daemon, err error) { return nil, err } d = &Daemon{ - layout: layout, - config: cfg, - store: db, - runner: system.NewRunner(), - logger: logger, - closing: make(chan struct{}), - pid: os.Getpid(), + layout: layout, + config: cfg, + store: db, + runner: system.NewRunner(), + logger: logger, + closing: make(chan struct{}), + pid: os.Getpid(), + sessionControllers: make(map[string]*guestSessionController), } d.ensureVMSSHClientConfig() d.logger.Info("daemon opened", "socket", layout.SocketPath, "state_dir", layout.StateDir, "log_level", cfg.LogLevel) diff --git a/internal/daemon/guest_sessions.go b/internal/daemon/guest_sessions.go index cf0f9d9..5aa1e68 100644 --- a/internal/daemon/guest_sessions.go +++ b/internal/daemon/guest_sessions.go @@ -494,18 +494,12 @@ func (d *Daemon) BeginGuestSessionAttach(ctx context.Context, params api.GuestSe func (d *Daemon) setGuestSessionController(id string, controller *guestSessionController) { d.mu.Lock() defer d.mu.Unlock() - if d.sessionControllers == nil { - d.sessionControllers = make(map[string]*guestSessionController) - } d.sessionControllers[id] = controller } func (d *Daemon) claimGuestSessionController(id string, controller *guestSessionController) bool { d.mu.Lock() defer d.mu.Unlock() - if d.sessionControllers == nil { - d.sessionControllers = make(map[string]*guestSessionController) - } if d.sessionControllers[id] != nil { return false } diff --git a/internal/daemon/vm.go b/internal/daemon/vm.go index b2dff48..8190163 100644 --- a/internal/daemon/vm.go +++ b/internal/daemon/vm.go @@ -298,7 +298,6 @@ func (d *Daemon) startVMLocked(ctx context.Context, vm model.VMRecord, image mod } op.stage("firecracker_launch", "log_path", vm.Runtime.LogPath, "metrics_path", vm.Runtime.MetricsPath) vmCreateStage(ctx, "boot_firecracker", "starting firecracker") - firecrackerCtx := context.Background() machineConfig := firecracker.MachineConfig{ BinaryPath: fcPath, VMID: vm.ID, @@ -322,15 +321,15 @@ func (d *Daemon) startVMLocked(ctx context.Context, vm model.VMRecord, image mod Logger: d.logger, } d.contributeMachineConfig(&machineConfig, vm, image) - machine, err := firecracker.NewMachine(firecrackerCtx, machineConfig) + machine, err := firecracker.NewMachine(ctx, machineConfig) if err != nil { return cleanupOnErr(err) } - if err := machine.Start(firecrackerCtx); err != nil { - vm.Runtime.PID = d.resolveFirecrackerPID(firecrackerCtx, machine, apiSock) + if err := machine.Start(ctx); err != nil { + vm.Runtime.PID = d.resolveFirecrackerPID(ctx, machine, apiSock) return cleanupOnErr(err) } - vm.Runtime.PID = d.resolveFirecrackerPID(firecrackerCtx, machine, apiSock) + vm.Runtime.PID = d.resolveFirecrackerPID(ctx, machine, apiSock) op.debugStage("firecracker_started", "pid", vm.Runtime.PID) op.stage("socket_access", "api_socket", apiSock) if err := d.ensureSocketAccess(ctx, apiSock, "firecracker api socket"); err != nil {