mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Fix deadlock on cancelling healthcheck
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
parent
27c20a7ea0
commit
89b1234737
3 changed files with 12 additions and 8 deletions
|
@ -42,10 +42,7 @@ func (s *Health) OpenMonitorChannel() chan struct{} {
|
||||||
func (s *Health) CloseMonitorChannel() {
|
func (s *Health) CloseMonitorChannel() {
|
||||||
if s.stop != nil {
|
if s.stop != nil {
|
||||||
logrus.Debug("CloseMonitorChannel: waiting for probe to stop")
|
logrus.Debug("CloseMonitorChannel: waiting for probe to stop")
|
||||||
// This channel does not buffer. Once the write succeeds, the monitor
|
close(s.stop)
|
||||||
// has read the stop request and will not make any further updates
|
|
||||||
// to c.State.Health.
|
|
||||||
s.stop <- struct{}{}
|
|
||||||
s.stop = nil
|
s.stop = nil
|
||||||
logrus.Debug("CloseMonitorChannel done")
|
logrus.Debug("CloseMonitorChannel done")
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,10 +107,17 @@ func (p *cmdProbe) run(ctx context.Context, d *Daemon, container *container.Cont
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the container's Status.Health struct based on the latest probe's result.
|
// Update the container's Status.Health struct based on the latest probe's result.
|
||||||
func handleProbeResult(d *Daemon, c *container.Container, result *types.HealthcheckResult) {
|
func handleProbeResult(d *Daemon, c *container.Container, result *types.HealthcheckResult, done chan struct{}) {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
|
||||||
|
// probe may have been cancelled while waiting on lock. Ignore result then
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
retries := c.Config.Healthcheck.Retries
|
retries := c.Config.Healthcheck.Retries
|
||||||
if retries <= 0 {
|
if retries <= 0 {
|
||||||
retries = defaultProbeRetries
|
retries = defaultProbeRetries
|
||||||
|
@ -183,7 +190,7 @@ func monitor(d *Daemon, c *container.Container, stop chan struct{}, probe probe)
|
||||||
cancelProbe()
|
cancelProbe()
|
||||||
return
|
return
|
||||||
case result := <-results:
|
case result := <-results:
|
||||||
handleProbeResult(d, c, result)
|
handleProbeResult(d, c, result, stop)
|
||||||
// Stop timeout
|
// Stop timeout
|
||||||
cancelProbe()
|
cancelProbe()
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
@ -193,7 +200,7 @@ func monitor(d *Daemon, c *container.Container, stop chan struct{}, probe probe)
|
||||||
Output: fmt.Sprintf("Health check exceeded timeout (%v)", probeTimeout),
|
Output: fmt.Sprintf("Health check exceeded timeout (%v)", probeTimeout),
|
||||||
Start: startTime,
|
Start: startTime,
|
||||||
End: time.Now(),
|
End: time.Now(),
|
||||||
})
|
}, stop)
|
||||||
cancelProbe()
|
cancelProbe()
|
||||||
// Wait for probe to exit (it might take a while to respond to the TERM
|
// Wait for probe to exit (it might take a while to respond to the TERM
|
||||||
// signal and we don't want dying probes to pile up).
|
// signal and we don't want dying probes to pile up).
|
||||||
|
|
|
@ -80,7 +80,7 @@ func TestHealthStates(t *testing.T) {
|
||||||
Start: startTime,
|
Start: startTime,
|
||||||
End: startTime,
|
End: startTime,
|
||||||
ExitCode: exitCode,
|
ExitCode: exitCode,
|
||||||
})
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// starting -> failed -> success -> failed
|
// starting -> failed -> success -> failed
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue