Merge pull request #22898 from WeiZhang555/add-detach-event

Add detach event
This commit is contained in:
Alexander Morozov 2016-06-03 09:49:48 -07:00
commit c80a2f2937
4 changed files with 42 additions and 12 deletions

View file

@ -48,6 +48,21 @@ var (
errInvalidNetwork = fmt.Errorf("invalid network settings while building port map info")
)
// AttachError represents errors of attach
type AttachError interface {
IsDetached() bool
}
type detachError struct{}
func (e detachError) IsDetached() bool {
return true
}
func (e detachError) Error() string {
return "detached from container"
}
// CommonContainer holds the fields for a container which are
// applicable across all platforms supported by the daemon.
type CommonContainer struct {
@ -393,7 +408,6 @@ func AttachStreams(ctx context.Context, streamConfig *runconfig.StreamConfig, op
_, err = copyEscapable(cStdin, stdin, keys)
} else {
_, err = io.Copy(cStdin, stdin)
}
if err == io.ErrClosedPipe {
err = nil
@ -492,10 +506,8 @@ func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64
break
}
if i == len(keys)-1 {
if err := src.Close(); err != nil {
return 0, err
}
return 0, nil
src.Close()
return 0, detachError{}
}
nr, er = src.Read(buf)
}

View file

@ -73,9 +73,9 @@ func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadClose
return daemon.containerAttach(container, stdin, stdout, stderr, false, stream, nil)
}
func (daemon *Daemon) containerAttach(container *container.Container, stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool, keys []byte) error {
func (daemon *Daemon) containerAttach(c *container.Container, stdin io.ReadCloser, stdout, stderr io.Writer, logs, stream bool, keys []byte) error {
if logs {
logDriver, err := daemon.getLogger(container)
logDriver, err := daemon.getLogger(c)
if err != nil {
return err
}
@ -105,7 +105,7 @@ func (daemon *Daemon) containerAttach(container *container.Container, stdin io.R
}
}
daemon.LogContainerEvent(container, "attach")
daemon.LogContainerEvent(c, "attach")
//stream
if stream {
@ -119,11 +119,20 @@ func (daemon *Daemon) containerAttach(container *container.Container, stdin io.R
}()
stdinPipe = r
}
<-container.Attach(stdinPipe, stdout, stderr, keys)
err := <-c.Attach(stdinPipe, stdout, stderr, keys)
if err != nil {
e, ok := err.(container.AttachError)
if ok && e.IsDetached() {
daemon.LogContainerEvent(c, "detach")
} else {
logrus.Errorf("attach failed with error: %v", err)
}
}
// If we are in stdinonce mode, wait for the process to end
// otherwise, simply return
if container.Config.StdinOnce && !container.Config.Tty {
container.WaitStop(-1 * time.Second)
if c.Config.StdinOnce && !c.Config.Tty {
c.WaitStop(-1 * time.Second)
}
}
return nil

View file

@ -222,7 +222,11 @@ func (d *Daemon) ContainerExecStart(ctx context.Context, name string, stdin io.R
return fmt.Errorf("context cancelled")
case err := <-attachErr:
if err != nil {
return fmt.Errorf("attach failed with error: %v", err)
e, ok := err.(container.AttachError)
if !ok || !e.IsDetached() {
return fmt.Errorf("attach failed with error: %v", err)
}
d.LogContainerEvent(c, "detach")
}
}
return nil

View file

@ -135,6 +135,11 @@ func (s *DockerSuite) TestRunAttachDetach(c *check.C) {
running := inspectField(c, name, "State.Running")
c.Assert(running, checker.Equals, "true", check.Commentf("expected container to still be running"))
out, _ = dockerCmd(c, "events", "--since=0", "--until", daemonUnixTime(c), "-f", "container="+name)
// attach and detach event should be monitored
c.Assert(out, checker.Contains, "attach")
c.Assert(out, checker.Contains, "detach")
}
// TestRunDetach checks attaching and detaching with the escape sequence specified via flags.