mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix an issue with service logs hanging
Fixed an issue where service logs would hang if the container backing a task was deleted by not waiting for containers to be ready if we're not following logs. Signed-off-by: Drew Erny <drew.erny@docker.com>
This commit is contained in:
parent
bf5cf84534
commit
80c3ec027d
2 changed files with 62 additions and 2 deletions
|
@ -437,9 +437,20 @@ func (r *controller) Logs(ctx context.Context, publisher exec.LogPublisher, opti
|
|||
return err
|
||||
}
|
||||
|
||||
if err := r.waitReady(ctx); err != nil {
|
||||
return errors.Wrap(err, "container not ready for logs")
|
||||
// if we're following, wait for this container to be ready. there is a
|
||||
// problem here: if the container will never be ready (for example, it has
|
||||
// been totally deleted) then this will wait forever. however, this doesn't
|
||||
// actually cause any UI issues, and shouldn't be a problem. the stuck wait
|
||||
// will go away when the follow (context) is canceled.
|
||||
if options.Follow {
|
||||
if err := r.waitReady(ctx); err != nil {
|
||||
return errors.Wrap(err, "container not ready for logs")
|
||||
}
|
||||
}
|
||||
// if we're not following, we're not gonna wait for the container to be
|
||||
// ready. just call logs. if the container isn't ready, the call will fail
|
||||
// and return an error. no big deal, we don't care, we only want the logs
|
||||
// we can get RIGHT NOW with no follow
|
||||
|
||||
logsContext, cancel := context.WithCancel(ctx)
|
||||
msgs, err := r.adapter.logs(logsContext, options)
|
||||
|
|
|
@ -283,3 +283,52 @@ func (s *DockerSwarmSuite) TestServiceLogsTTY(c *check.C) {
|
|||
// just expected.
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{Out: "out\r\nerr\r\n"})
|
||||
}
|
||||
|
||||
func (s *DockerSwarmSuite) TestServiceLogsNoHangDeletedContainer(c *check.C) {
|
||||
d := s.AddDaemon(c, true, true)
|
||||
|
||||
name := "TestServiceLogsNoHangDeletedContainer"
|
||||
|
||||
result := icmd.RunCmd(d.Command(
|
||||
// create a service
|
||||
"service", "create",
|
||||
// name it $name
|
||||
"--name", name,
|
||||
// busybox image, shell string
|
||||
"busybox", "sh", "-c",
|
||||
// echo to stdout and stderr
|
||||
"while true; do echo line; sleep 2; done",
|
||||
))
|
||||
|
||||
// confirm that the command succeeded
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{})
|
||||
// get the service id
|
||||
id := strings.TrimSpace(result.Stdout())
|
||||
c.Assert(id, checker.Not(checker.Equals), "")
|
||||
|
||||
// make sure task has been deployed.
|
||||
waitAndAssert(c, defaultReconciliationTimeout, d.CheckActiveContainerCount, checker.Equals, 1)
|
||||
// and make sure we have all the log lines
|
||||
waitAndAssert(c, defaultReconciliationTimeout, countLogLines(d, name), checker.Equals, 2)
|
||||
|
||||
// now find and nuke the container
|
||||
result = icmd.RunCmd(d.Command("ps", "-q"))
|
||||
containerID := strings.TrimSpace(result.Stdout())
|
||||
c.Assert(containerID, checker.Not(checker.Equals), "")
|
||||
result = icmd.RunCmd(d.Command("stop", containerID))
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{Out: containerID})
|
||||
result = icmd.RunCmd(d.Command("rm", containerID))
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{Out: containerID})
|
||||
|
||||
// run logs. use tail 2 to make sure we don't try to get a bunch of logs
|
||||
// somehow and slow down execution time
|
||||
cmd := d.Command("service", "logs", "--tail", "2", id)
|
||||
// start the command and then wait for it to finish with a 3 second timeout
|
||||
result = icmd.StartCmd(cmd)
|
||||
result = icmd.WaitOnCmd(3*time.Second, result)
|
||||
|
||||
// then, assert that the result matches expected. if the command timed out,
|
||||
// if the command is timed out, result.Timeout will be true, but the
|
||||
// Expected defaults to false
|
||||
c.Assert(result, icmd.Matches, icmd.Expected{})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue