diff options
Diffstat (limited to 'libpod/container.go')
-rw-r--r-- | libpod/container.go | 255 |
1 files changed, 162 insertions, 93 deletions
diff --git a/libpod/container.go b/libpod/container.go index a34394792..e26235e26 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -348,11 +348,13 @@ func (c *Container) LogPath() string { // IPAddress returns the IP address of the container // If the container does not have a network namespace, an error will be returned func (c *Container) IPAddress() (net.IP, error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return nil, errors.Wrapf(err, "error updating container %s state", c.ID()) + if err := c.syncContainer(); err != nil { + return nil, errors.Wrapf(err, "error updating container %s state", c.ID()) + } } if !c.config.CreateNetNS || c.state.NetNS == nil { @@ -365,10 +367,12 @@ func (c *Container) IPAddress() (net.IP, error) { // ExitCode returns the exit code of the container as // an int32 func (c *Container) ExitCode() (int32, error) { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return 0, errors.Wrapf(err, "error updating container %s state", c.ID()) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return 0, errors.Wrapf(err, "error updating container %s state", c.ID()) + } } return c.state.ExitCode, nil } @@ -376,10 +380,12 @@ func (c *Container) ExitCode() (int32, error) { // Mounted returns a bool as to if the container's storage // is mounted func (c *Container) Mounted() (bool, error) { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return false, errors.Wrapf(err, "error updating container %s state", c.ID()) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return false, errors.Wrapf(err, "error updating container %s state", c.ID()) + } } return c.state.Mounted, nil } @@ -387,41 +393,49 @@ func (c *Container) Mounted() (bool, error) { // Mountpoint returns the path to the container's mounted // storage as a string func (c *Container) Mountpoint() (string, error) { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + } } return c.state.Mountpoint, nil } // StartedTime is the time the container was started func (c *Container) StartedTime() (time.Time, error) { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + } } return c.state.StartedTime, nil } // FinishedTime is the time the container was stopped func (c *Container) FinishedTime() (time.Time, error) { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return time.Time{}, errors.Wrapf(err, "error updating container %s state", c.ID()) + } } return c.state.FinishedTime, nil } // State returns the current state of the container func (c *Container) State() (ContainerState, error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return ContainerStateUnknown, err + if err := c.syncContainer(); err != nil { + return ContainerStateUnknown, err + } } return c.state.State, nil } @@ -429,11 +443,13 @@ func (c *Container) State() (ContainerState, error) { // PID returns the PID of the container // An error is returned if the container is not running func (c *Container) PID() (int, error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return -1, err + if err := c.syncContainer(); err != nil { + return -1, err + } } return c.state.PID, nil @@ -441,10 +457,12 @@ func (c *Container) PID() (int, error) { // MountPoint returns the mount point of the continer func (c *Container) MountPoint() (string, error) { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return "", errors.Wrapf(err, "error updating container %s state", c.ID()) + } } return c.state.Mountpoint, nil } @@ -612,11 +630,13 @@ func (c *Container) refresh() error { // Init creates a container in the OCI runtime func (c *Container) Init() (err error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } if c.state.State != ContainerStateConfigured { @@ -761,11 +781,13 @@ func (c *Container) Init() (err error) { // Start starts a container func (c *Container) Start() error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } // Container must be created or stopped to be started @@ -797,14 +819,17 @@ func (c *Container) Start() error { // seconds), uses SIGKILL to attempt to forcibly stop the container. // If timeout is 0, SIGKILL will be used immediately func (c *Container) Stop(timeout uint) error { - c.lock.Lock() - defer c.lock.Unlock() - logrus.Debugf("Stopping ctr %s with timeout %d", c.ID(), timeout) + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } + logrus.Debugf("Stopping ctr %s with timeout %d", c.ID(), timeout) + if c.state.State == ContainerStateConfigured || c.state.State == ContainerStateUnknown || c.state.State == ContainerStatePaused { @@ -825,11 +850,13 @@ func (c *Container) Stop(timeout uint) error { // Kill sends a signal to a container func (c *Container) Kill(signal uint) error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } if c.state.State != ContainerStateRunning { @@ -842,11 +869,14 @@ func (c *Container) Kill(signal uint) error { // Exec starts a new process inside the container func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) error { var capList []string - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + + if err := c.syncContainer(); err != nil { + return err + } } conState := c.state.State @@ -875,8 +905,13 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e // Attach attaches to a container // Returns fully qualified URL of streaming server for the container func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) error { - if err := c.syncContainer(); err != nil { - return err + if !c.locked { + c.lock.Lock() + if err := c.syncContainer(); err != nil { + c.lock.Unlock() + return err + } + c.lock.Unlock() } if c.state.State != ContainerStateCreated && @@ -904,11 +939,13 @@ func (c *Container) Attach(noStdin bool, keys string, attached chan<- bool) erro // Mount mounts a container's filesystem on the host // The path where the container has been mounted is returned func (c *Container) Mount(label string) (string, error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return "", err + if err := c.syncContainer(); err != nil { + return "", err + } } // return mountpoint if container already mounted @@ -937,11 +974,13 @@ func (c *Container) Mount(label string) (string, error) { // Unmount unmounts a container's filesystem on the host func (c *Container) Unmount() error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } if c.state.State == ContainerStateRunning || c.state.State == ContainerStatePaused { @@ -953,11 +992,13 @@ func (c *Container) Unmount() error { // Pause pauses a container func (c *Container) Pause() error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } if c.state.State == ContainerStatePaused { @@ -982,11 +1023,13 @@ func (c *Container) Pause() error { // Unpause unpauses a container func (c *Container) Unpause() error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } if c.state.State != ContainerStatePaused { @@ -1009,11 +1052,13 @@ func (c *Container) Unpause() error { // Export exports a container's root filesystem as a tar archive // The archive will be saved as a file at the given path func (c *Container) Export(path string) error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } return c.export(path) @@ -1051,16 +1096,28 @@ func (c *Container) export(path string) error { // AddArtifact creates and writes to an artifact file for the container func (c *Container) AddArtifact(name string, data []byte) error { + if !c.valid { + return ErrCtrRemoved + } + return ioutil.WriteFile(c.getArtifactPath(name), data, 0740) } // GetArtifact reads the specified artifact file from the container func (c *Container) GetArtifact(name string) ([]byte, error) { + if !c.valid { + return nil, ErrCtrRemoved + } + return ioutil.ReadFile(c.getArtifactPath(name)) } // RemoveArtifact deletes the specified artifacts file func (c *Container) RemoveArtifact(name string) error { + if !c.valid { + return ErrCtrRemoved + } + return os.Remove(c.getArtifactPath(name)) } @@ -1070,11 +1127,13 @@ func (c *Container) getArtifactPath(name string) string { // Inspect a container for low-level information func (c *Container) Inspect(size bool) (*ContainerInspectData, error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return nil, err + if err := c.syncContainer(); err != nil { + return nil, err + } } storeCtr, err := c.runtime.store.Container(c.ID()) @@ -1096,11 +1155,13 @@ func (c *Container) Inspect(size bool) (*ContainerInspectData, error) { // Commit commits the changes between a container and its image, creating a new // image func (c *Container) Commit(pause bool, options CopyOptions) error { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if err := c.syncContainer(); err != nil { + return err + } } if c.state.State == ContainerStateRunning && pause { @@ -1129,6 +1190,10 @@ func (c *Container) Commit(pause bool, options CopyOptions) error { // Wait blocks on a container to exit and returns its exit code func (c *Container) Wait() (int32, error) { + if !c.valid { + return -1, ErrCtrRemoved + } + err := wait.PollImmediateInfinite(1, func() (bool, error) { stopped, err := c.isStopped() @@ -1150,8 +1215,10 @@ func (c *Container) Wait() (int32, error) { } func (c *Container) isStopped() (bool, error) { - c.lock.Lock() - defer c.lock.Unlock() + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + } err := c.syncContainer() if err != nil { return true, err @@ -1215,10 +1282,12 @@ func (c *Container) mountStorage() (err error) { // CleanupStorage unmounts all mount points in container and cleans up container storage func (c *Container) CleanupStorage() error { - c.lock.Lock() - defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return err + } } return c.cleanupStorage() } |