diff options
author | Matthew Heon <matthew.heon@pm.me> | 2019-05-14 14:54:21 -0400 |
---|---|---|
committer | Matthew Heon <matthew.heon@pm.me> | 2019-05-14 14:54:21 -0400 |
commit | d83d0abfbf6f914303c1b33d954aa115accbd999 (patch) | |
tree | 1842018b4c49e4c2a379de239833cb8f6bbda229 /libpod/container_attach_linux.go | |
parent | a261b60cc8851c04efd191be6f6e2e4598439822 (diff) | |
download | podman-d83d0abfbf6f914303c1b33d954aa115accbd999.tar.gz podman-d83d0abfbf6f914303c1b33d954aa115accbd999.tar.bz2 podman-d83d0abfbf6f914303c1b33d954aa115accbd999.zip |
Ensure that start() in StartAndAttach() is locked
StartAndAttach() runs start() in a goroutine, which can allow it
to fire after the caller returns - and thus, after the defer to
unlock the container lock has fired.
The start() call _must_ occur while the container is locked, or
else state inconsistencies may occur.
Fixes #3114
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
Diffstat (limited to 'libpod/container_attach_linux.go')
-rw-r--r-- | libpod/container_attach_linux.go | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/libpod/container_attach_linux.go b/libpod/container_attach_linux.go index 3ff6ddc76..7e9b7697b 100644 --- a/libpod/container_attach_linux.go +++ b/libpod/container_attach_linux.go @@ -8,6 +8,7 @@ import ( "net" "os" "path/filepath" + "sync" "github.com/containers/libpod/pkg/kubeutils" "github.com/containers/libpod/utils" @@ -31,7 +32,7 @@ const ( // Attach to the given container // Does not check if state is appropriate -func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error { +func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error { if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput { return errors.Wrapf(ErrInvalidArg, "must provide at least one stream to attach to") } @@ -48,12 +49,17 @@ func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan re logrus.Debugf("Attaching to container %s", c.ID()) - return c.attachContainerSocket(resize, detachKeys, streams, startContainer) + return c.attachContainerSocket(resize, detachKeys, streams, startContainer, wg) } -// attachContainerSocket connects to the container's attach socket and deals with the IO +// attachContainerSocket connects to the container's attach socket and deals with the IO. +// wg is only required if startContainer is true // TODO add a channel to allow interrupting -func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool) error { +func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool, wg *sync.WaitGroup) error { + if startContainer && wg == nil { + return errors.Wrapf(ErrInternal, "wait group not passed when startContainer set") + } + kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) { controlPath := filepath.Join(c.bundlePath(), "ctl") controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0) @@ -84,10 +90,13 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi } defer conn.Close() + // If starting was requested, start the container and notify when that's + // done. if startContainer { if err := c.start(); err != nil { return err } + wg.Done() } receiveStdoutError := make(chan error) |