daemon_linux_test.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package container // import "github.com/docker/docker/integration/container"
  2. import (
  3. "context"
  4. "fmt"
  5. "io/ioutil"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "github.com/docker/docker/api/types"
  10. "github.com/docker/docker/integration/internal/container"
  11. "github.com/docker/docker/internal/test/daemon"
  12. "golang.org/x/sys/unix"
  13. "gotest.tools/assert"
  14. "gotest.tools/skip"
  15. )
  16. // This is a regression test for #36145
  17. // It ensures that a container can be started when the daemon was improperly
  18. // shutdown when the daemon is brought back up.
  19. //
  20. // The regression is due to improper error handling preventing a container from
  21. // being restored and as such have the resources cleaned up.
  22. //
  23. // To test this, we need to kill dockerd, then kill both the containerd-shim and
  24. // the container process, then start dockerd back up and attempt to start the
  25. // container again.
  26. func TestContainerStartOnDaemonRestart(t *testing.T) {
  27. skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run")
  28. skip.If(t, testEnv.DaemonInfo.OSType == "windows")
  29. t.Parallel()
  30. d := daemon.New(t)
  31. d.StartWithBusybox(t, "--iptables=false")
  32. defer d.Stop(t)
  33. c := d.NewClientT(t)
  34. ctx := context.Background()
  35. cID := container.Create(t, ctx, c)
  36. defer c.ContainerRemove(ctx, cID, types.ContainerRemoveOptions{Force: true})
  37. err := c.ContainerStart(ctx, cID, types.ContainerStartOptions{})
  38. assert.Check(t, err, "error starting test container")
  39. inspect, err := c.ContainerInspect(ctx, cID)
  40. assert.Check(t, err, "error getting inspect data")
  41. ppid := getContainerdShimPid(t, inspect)
  42. err = d.Kill()
  43. assert.Check(t, err, "failed to kill test daemon")
  44. err = unix.Kill(inspect.State.Pid, unix.SIGKILL)
  45. assert.Check(t, err, "failed to kill container process")
  46. err = unix.Kill(ppid, unix.SIGKILL)
  47. assert.Check(t, err, "failed to kill containerd-shim")
  48. d.Start(t, "--iptables=false")
  49. err = c.ContainerStart(ctx, cID, types.ContainerStartOptions{})
  50. assert.Check(t, err, "failed to start test container")
  51. }
  52. func getContainerdShimPid(t *testing.T, c types.ContainerJSON) int {
  53. statB, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", c.State.Pid))
  54. assert.Check(t, err, "error looking up containerd-shim pid")
  55. // ppid is the 4th entry in `/proc/pid/stat`
  56. ppid, err := strconv.Atoi(strings.Fields(string(statB))[3])
  57. assert.Check(t, err, "error converting ppid field to int")
  58. assert.Check(t, ppid != 1, "got unexpected ppid")
  59. return ppid
  60. }