Handle signal preventing Start from completing

In the instance where the user sends a signal, such as SIGINT (Ctl-c)
when a Podman Machine is in the middle of starting, make sure the state
doesn't get stuck in the "Currently Starting" status.

Resolves: #24416

Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me>
This commit is contained in:
Jake Correnti
2025-04-08 11:56:21 -04:00
parent 20e1b9db3a
commit 24267452e6

View File

@ -6,10 +6,12 @@ import (
"fmt"
"io"
"os"
"os/signal"
"path"
"path/filepath"
"runtime"
"strings"
"syscall"
"time"
"github.com/containers/podman/v5/pkg/machine"
@ -440,6 +442,7 @@ func stopLocked(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *mach
func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDefine.MachineDirs, opts machine.StartOptions) error {
defaultBackoff := 500 * time.Millisecond
maxBackoffs := 6
signalChanClosed := false
mc.Lock()
defer mc.Unlock()
@ -471,17 +474,41 @@ func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDe
}
}
// if the machine cannot continue starting due to a signal, ensure the state
// reflects the machine is no longer starting
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
go func() {
sig, ok := <-signalChan
if ok {
mc.Starting = false
logrus.Error("signal received when starting the machine: ", sig)
if err := mc.Write(); err != nil {
logrus.Error(err)
}
os.Exit(1)
}
}()
// Set starting to true
mc.Starting = true
if err := mc.Write(); err != nil {
logrus.Error(err)
}
// Set starting to false on exit
defer func() {
mc.Starting = false
if err := mc.Write(); err != nil {
logrus.Error(err)
}
if !signalChanClosed {
signal.Stop(signalChan)
close(signalChan)
}
}()
gvproxyPidFile, err := dirs.RuntimeDir.AppendToNewVMFile("gvproxy.pid", nil)
@ -557,6 +584,11 @@ func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDe
return errors.New(msg)
}
// now that the machine has transitioned into the running state, we don't need a goroutine listening for SIGINT or SIGTERM to handle state
signal.Stop(signalChan)
close(signalChan)
signalChanClosed = true
if err := proxyenv.ApplyProxies(mc); err != nil {
return err
}