daemon_linux_test.go 2.3 KB

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