Skip to content

Commit da8e44a

Browse files
authored
Merge pull request #429 from Joffref/sugate/fix-stop-vmm
Wait for cleanup to be done after stop VMM
2 parents 09f1a82 + 5146da5 commit da8e44a

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/sirupsen/logrus v1.8.1
1919
github.com/stretchr/testify v1.8.0
2020
github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5
21+
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f
2122
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
2223
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a
2324
)

machine.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,8 @@ type Machine struct {
270270
// callbacks that should be run when the machine is being torn down
271271
cleanupOnce sync.Once
272272
cleanupFuncs []func() error
273+
// cleanupCh is a channel that gets closed to notify cleanup cleanupFuncs has been called totally
274+
cleanupCh chan struct{}
273275
}
274276

275277
// Logger returns a logrus logger appropriate for logging hypervisor messages
@@ -354,7 +356,8 @@ func configureBuilder(builder VMCommandBuilder, cfg Config) VMCommandBuilder {
354356
// provided Config.
355357
func NewMachine(ctx context.Context, cfg Config, opts ...Opt) (*Machine, error) {
356358
m := &Machine{
357-
exitCh: make(chan struct{}),
359+
exitCh: make(chan struct{}),
360+
cleanupCh: make(chan struct{}),
358361
}
359362

360363
if cfg.VMID == "" {
@@ -594,6 +597,8 @@ func (m *Machine) startVMM(ctx context.Context) error {
594597
// When err is nil, two reads are performed (waitForSocket and close exitCh goroutine),
595598
// second one never ends as it tries to read from empty channel.
596599
close(errCh)
600+
close(m.cleanupCh)
601+
597602
}()
598603

599604
m.setupSignals()
@@ -642,6 +647,8 @@ func (m *Machine) stopVMM() error {
642647
if err != nil && !strings.Contains(err.Error(), "os: process already finished") {
643648
return err
644649
}
650+
// Wait for the cleanup to finish.
651+
<-m.cleanupCh
645652
return nil
646653
}
647654
m.logger.Debug("stopVMM(): no firecracker process running, not sending a signal")

machine_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"errors"
2020
"flag"
2121
"fmt"
22+
"github.com/vishvananda/netns"
2223
"io"
2324
"io/ioutil"
2425
"net"
@@ -799,6 +800,71 @@ func testStopVMM(ctx context.Context, t *testing.T, m *Machine) {
799800
}
800801
}
801802

803+
func TestStopVMMCleanup(t *testing.T) {
804+
fctesting.RequiresKVM(t)
805+
fctesting.RequiresRoot(t)
806+
807+
socketPath, cleanup := makeSocketPath(t)
808+
defer cleanup()
809+
810+
dir, err := ioutil.TempDir("", t.Name())
811+
require.NoError(t, err)
812+
defer os.RemoveAll(dir)
813+
814+
cniConfDir := filepath.Join(dir, "cni.conf")
815+
err = os.MkdirAll(cniConfDir, 0777)
816+
require.NoError(t, err)
817+
818+
cniBinPath := []string{testDataBin}
819+
820+
const networkName = "fcnet"
821+
const ifName = "veth0"
822+
823+
networkMask := "/24"
824+
subnet := "10.168.0.0" + networkMask
825+
826+
cniConfPath := fmt.Sprintf("%s/%s.conflist", cniConfDir, networkName)
827+
err = writeCNIConfWithHostLocalSubnet(cniConfPath, networkName, subnet)
828+
require.NoError(t, err)
829+
defer os.Remove(cniConfPath)
830+
831+
networkInterface := NetworkInterface{
832+
CNIConfiguration: &CNIConfiguration{
833+
NetworkName: networkName,
834+
IfName: ifName,
835+
ConfDir: cniConfDir,
836+
BinPath: cniBinPath,
837+
VMIfName: "eth0",
838+
},
839+
}
840+
841+
cfg := Config{
842+
SocketPath: socketPath,
843+
DisableValidation: true,
844+
KernelImagePath: getVmlinuxPath(t),
845+
NetworkInterfaces: []NetworkInterface{networkInterface},
846+
MachineCfg: models.MachineConfiguration{
847+
VcpuCount: Int64(1),
848+
MemSizeMib: Int64(64),
849+
CPUTemplate: models.CPUTemplate(models.CPUTemplateT2),
850+
Smt: Bool(false),
851+
},
852+
}
853+
ctx := context.Background()
854+
cmd := VMCommandBuilder{}.
855+
WithSocketPath(cfg.SocketPath).
856+
WithBin(getFirecrackerBinaryPath()).
857+
Build(ctx)
858+
m, err := NewMachine(ctx, cfg, WithProcessRunner(cmd), WithLogger(fctesting.NewLogEntry(t)))
859+
require.NoError(t, err)
860+
err = m.Start(ctx)
861+
require.NoError(t, err)
862+
err = m.stopVMM()
863+
require.NoError(t, err)
864+
_, err = netns.GetFromName(m.Cfg.VMID)
865+
require.Error(t, err)
866+
}
867+
802868
func testShutdown(ctx context.Context, t *testing.T, m *Machine) {
803869
err := m.Shutdown(ctx)
804870
if err != nil {

0 commit comments

Comments
 (0)