103 lines
3.6 KiB
Diff
103 lines
3.6 KiB
Diff
|
|
From 50af5f9c3fead1cca65c088c920d36faa5b29264 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Brian Goff <cpuguy83@gmail.com>
|
||
|
|
Date: Tue, 7 Apr 2020 17:03:32 -0700
|
||
|
|
Subject: [PATCH 06/14] On startup, actually shutdown the container.
|
||
|
|
|
||
|
|
When a container is left running after the daemon exits (e.g. the daemon
|
||
|
|
is SIGKILL'd or crashes), it should stop any running containers when the
|
||
|
|
daemon starts back up.
|
||
|
|
|
||
|
|
What actually happens is the daemon only sends the container's
|
||
|
|
configured stop signal and does not check if it has exited.
|
||
|
|
If the container does not actually exit then it is left running.
|
||
|
|
|
||
|
|
This fixes this unexpected behavior by calling the same function to shut
|
||
|
|
down the container that the daemon shutdown process does.
|
||
|
|
|
||
|
|
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
|
||
|
|
Upstream-commit: ced91bee4b54c6acc3271e6ed28e0496a344321f
|
||
|
|
Component: engine
|
||
|
|
---
|
||
|
|
components/engine/daemon/daemon.go | 3 +-
|
||
|
|
.../integration/container/daemon_test.go | 51 +++++++++++++++++++
|
||
|
|
2 files changed, 53 insertions(+), 1 deletion(-)
|
||
|
|
create mode 100644 components/engine/integration/container/daemon_test.go
|
||
|
|
|
||
|
|
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||
|
|
index 96cfb14bf8..8754492cef 100644
|
||
|
|
--- a/components/engine/daemon/daemon.go
|
||
|
|
+++ b/components/engine/daemon/daemon.go
|
||
|
|
@@ -397,10 +397,11 @@ func (daemon *Daemon) restore() error {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
} else if !daemon.configStore.LiveRestoreEnabled {
|
||
|
|
- if err := daemon.kill(c, c.StopSignal()); err != nil && !errdefs.IsNotFound(err) {
|
||
|
|
+ if err := daemon.shutdownContainer(c); err != nil && !errdefs.IsNotFound(err) {
|
||
|
|
logrus.WithError(err).WithField("container", c.ID).Error("error shutting down container")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
+ c.ResetRestartManager(false)
|
||
|
|
}
|
||
|
|
|
||
|
|
if alive && !c.IsRunning() && pid > 1 {
|
||
|
|
diff --git a/components/engine/integration/container/daemon_test.go b/components/engine/integration/container/daemon_test.go
|
||
|
|
new file mode 100644
|
||
|
|
index 0000000000..94468a4409
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/components/engine/integration/container/daemon_test.go
|
||
|
|
@@ -0,0 +1,51 @@
|
||
|
|
+package container
|
||
|
|
+
|
||
|
|
+import (
|
||
|
|
+ "context"
|
||
|
|
+ "testing"
|
||
|
|
+
|
||
|
|
+ "github.com/docker/docker/api/types"
|
||
|
|
+ "github.com/docker/docker/integration/internal/container"
|
||
|
|
+ "github.com/docker/docker/testutil/daemon"
|
||
|
|
+ "gotest.tools/v3/assert"
|
||
|
|
+ is "gotest.tools/v3/assert/cmp"
|
||
|
|
+ "gotest.tools/v3/skip"
|
||
|
|
+)
|
||
|
|
+
|
||
|
|
+// Make sure a container that does not exit when it upon receiving it's stop signal is actually shutdown on daemon
|
||
|
|
+// startup.
|
||
|
|
+func TestContainerKillOnDaemonStart(t *testing.T) {
|
||
|
|
+ skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run")
|
||
|
|
+ skip.If(t, testEnv.DaemonInfo.OSType == "windows")
|
||
|
|
+ skip.If(t, testEnv.IsRootless, "scenario doesn't work with rootless mode")
|
||
|
|
+
|
||
|
|
+ t.Parallel()
|
||
|
|
+
|
||
|
|
+ d := daemon.New(t)
|
||
|
|
+ defer d.Cleanup(t)
|
||
|
|
+
|
||
|
|
+ d.StartWithBusybox(t, "--iptables=false")
|
||
|
|
+ defer d.Stop(t)
|
||
|
|
+
|
||
|
|
+ client := d.NewClientT(t)
|
||
|
|
+ ctx := context.Background()
|
||
|
|
+
|
||
|
|
+ // The intention of this container is to ignore stop signals.
|
||
|
|
+ // Sadly this means the test will take longer, but at least this test can be parallelized.
|
||
|
|
+ id := container.Run(ctx, t, client, container.WithCmd("/bin/sh", "-c", "while true; do echo hello; sleep 1; done"))
|
||
|
|
+ defer func() {
|
||
|
|
+ err := client.ContainerRemove(ctx, id, types.ContainerRemoveOptions{Force: true})
|
||
|
|
+ assert.NilError(t, err)
|
||
|
|
+ }()
|
||
|
|
+
|
||
|
|
+ inspect, err := client.ContainerInspect(ctx, id)
|
||
|
|
+ assert.NilError(t, err)
|
||
|
|
+ assert.Assert(t, inspect.State.Running)
|
||
|
|
+
|
||
|
|
+ assert.NilError(t, d.Kill())
|
||
|
|
+ d.Start(t)
|
||
|
|
+
|
||
|
|
+ inspect, err = client.ContainerInspect(ctx, id)
|
||
|
|
+ assert.Check(t, is.Nil(err))
|
||
|
|
+ assert.Assert(t, !inspect.State.Running)
|
||
|
|
+}
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|