diff options
-rw-r--r-- | cmd/podman/ps.go | 5 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 7 | ||||
-rw-r--r-- | completions/bash/podman | 1 | ||||
-rw-r--r-- | docs/podman-ps.1.md | 7 | ||||
-rw-r--r-- | libpod/container_api.go | 21 |
5 files changed, 33 insertions, 8 deletions
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index 0b03388a2..7a4a80769 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -200,6 +200,10 @@ var ( Usage: "Sort output by command, created, id, image, names, runningfor, size, or status", Value: "created", }, + cli.BoolFlag{ + Name: "sync", + Usage: "Sync container state with OCI runtime", + }, } psDescription = "Prints out information about the containers" psCommand = cli.Command{ @@ -260,6 +264,7 @@ func psCmd(c *cli.Context) error { Size: c.Bool("size"), Namespace: c.Bool("namespace"), Sort: c.String("sort"), + Sync: c.Bool("sync"), } filters := c.StringSlice("filter") diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go index d0e892961..90ce193f7 100644 --- a/cmd/podman/shared/container.go +++ b/cmd/podman/shared/container.go @@ -45,6 +45,7 @@ type PsOptions struct { Sort string Label string Namespace bool + Sync bool } // BatchContainerStruct is the return obkect from BatchContainer and contains @@ -126,6 +127,12 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput pso PsContainerOutput ) batchErr := ctr.Batch(func(c *libpod.Container) error { + if opts.Sync { + if err := c.Sync(); err != nil { + return err + } + } + conState, err = c.State() if err != nil { return errors.Wrapf(err, "unable to obtain container state") diff --git a/completions/bash/podman b/completions/bash/podman index 9518cfa22..80ea53a74 100644 --- a/completions/bash/podman +++ b/completions/bash/podman @@ -2037,6 +2037,7 @@ _podman_ps() { --quiet -q --size -s --namespace --ns + --sync " _complete_ "$options_with_args" "$boolean_options" } diff --git a/docs/podman-ps.1.md b/docs/podman-ps.1.md index 7333a1095..8b86703d8 100644 --- a/docs/podman-ps.1.md +++ b/docs/podman-ps.1.md @@ -103,6 +103,13 @@ Valid filters are listed below: Print usage statement +**--sync** + +Force a sync of container state with the OCI runtime. +In some cases, a container's state in the runtime can become out of sync with Podman's state. +This will update Podman's state based on what the OCI runtime reports. +Forcibly syncing is much slower, but can resolve inconsistent state issues. + ## EXAMPLES ``` diff --git a/libpod/container_api.go b/libpod/container_api.go index bc92cae69..09bc46905 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -675,22 +675,27 @@ func (c *Container) Batch(batchFunc func(*Container) error) error { return err } -// Sync updates the current state of the container, checking whether its state -// has changed -// Sync can only be used inside Batch() - otherwise, it will be done -// automatically. -// When called outside Batch(), Sync() is a no-op +// Sync updates the status of a container by querying the OCI runtime. +// If the container has not been created inside the OCI runtime, nothing will be +// done. +// Most of the time, Podman does not explicitly query the OCI runtime for +// container status, and instead relies upon exit files created by conmon. +// This can cause a disconnect between running state and what Podman sees in +// cases where Conmon was killed unexpected, or runc was upgraded. +// Running a manual Sync() ensures that container state will be correct in +// such situations. func (c *Container) Sync() error { if !c.batched { - return nil + c.lock.Lock() + defer c.lock.Unlock() } // If runtime knows about the container, update its status in runtime // And then save back to disk if (c.state.State != ContainerStateUnknown) && - (c.state.State != ContainerStateConfigured) { + (c.state.State != ContainerStateConfigured) && + (c.state.State != ContainerStateExited) { oldState := c.state.State - // TODO: optionally replace this with a stat for the exit file if err := c.runtime.ociRuntime.updateContainerStatus(c, true); err != nil { return err } |