mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
Update Container Wait Backend
This patch consolidates the two WaitStop and WaitWithContext methods on the container.State type. Now there is a single method, Wait, which takes a context and a bool specifying whether to wait for not just a container exit but also removal. The behavior has been changed slightly so that a wait call during a Created state will not return immediately but instead wait for the container to be started and then exited. The interface has been changed to no longer block, but instead returns a channel on which the caller can receive a *StateStatus value which indicates the ExitCode or an error if there was one (like a context timeout or state transition error). These changes have been propagated through the rest of the deamon to preserve all other existing behavior. Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
@@ -60,7 +61,10 @@ func (daemon *Daemon) containerStop(container *container.Container, seconds int)
|
||||
// So, instead we'll give it up to 2 more seconds to complete and if
|
||||
// by that time the container is still running, then the error
|
||||
// we got is probably valid and so we force kill it.
|
||||
if _, err := container.WaitStop(2 * time.Second); err != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if status := <-container.Wait(ctx, false); status.Err() != nil {
|
||||
logrus.Infof("Container failed to stop after sending signal %d to the process, force killing", stopSignal)
|
||||
if err := daemon.killPossiblyDeadProcess(container, 9); err != nil {
|
||||
return err
|
||||
@@ -69,11 +73,15 @@ func (daemon *Daemon) containerStop(container *container.Container, seconds int)
|
||||
}
|
||||
|
||||
// 2. Wait for the process to exit on its own
|
||||
if _, err := container.WaitStop(time.Duration(seconds) * time.Second); err != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if status := <-container.Wait(ctx, false); status.Err() != nil {
|
||||
logrus.Infof("Container %v failed to exit within %d seconds of signal %d - using the force", container.ID, seconds, stopSignal)
|
||||
// 3. If it doesn't, then send SIGKILL
|
||||
if err := daemon.Kill(container); err != nil {
|
||||
container.WaitStop(-1 * time.Second)
|
||||
// Wait without a timeout, ignore result.
|
||||
_ = <-container.Wait(context.Background(), false)
|
||||
logrus.Warn(err) // Don't return error because we only care that container is stopped, not what function stopped it
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user