From 74bd1d0c00c53f96696663e45507e332684dac7a Mon Sep 17 00:00:00 2001 From: xiadanni Date: Wed, 3 Mar 2021 16:46:50 +0800 Subject: [PATCH] docker: fix docker kill command block reason:When docker kill command execute with start/restart command concurrently, kill command may block at <-container.Wait. As s.waitStop is variable, so there is case that waitStop in Wait function get a new s.waitStop(the old one is already closed before). So kill command blocked to wait the new s.waitStop close. Signed-off-by: xiadanni --- components/engine/container/state.go | 13 +++++++++++-- components/engine/daemon/kill.go | 4 +++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/components/engine/container/state.go b/components/engine/container/state.go index 91ea30a..e9666ed 100644 --- a/components/engine/container/state.go +++ b/components/engine/container/state.go @@ -65,6 +65,10 @@ func NewState() *State { } } +func (s State) GetWaitStop() chan struct{} { + return s.waitStop +} + // String returns a human-readable description of the state func (s *State) String() string { if s.Running { @@ -179,6 +183,10 @@ const ( // otherwise, the results Err() method will return an error indicating why the // wait operation failed. func (s *State) Wait(ctx context.Context, condition WaitCondition) <-chan StateStatus { + return s.Wait3(ctx, condition, nil) +} + +func (s *State) Wait3(ctx context.Context, condition WaitCondition, waitStop chan struct{}) <-chan StateStatus { s.Lock() defer s.Unlock() @@ -197,9 +205,10 @@ func (s *State) Wait(ctx context.Context, condition WaitCondition) <-chan StateS // If we are waiting only for removal, the waitStop channel should // remain nil and block forever. - var waitStop chan struct{} if condition < WaitConditionRemoved { - waitStop = s.waitStop + if waitStop == nil { + waitStop = s.waitStop + } } // Always wait for removal, just in case the container gets removed diff --git a/components/engine/daemon/kill.go b/components/engine/daemon/kill.go index d185065..4c8ccf9 100644 --- a/components/engine/daemon/kill.go +++ b/components/engine/daemon/kill.go @@ -132,6 +132,8 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error { return nil } + waitStop := container.GetWaitStop() + // 1. Send SIGKILL if err := daemon.killPossiblyDeadProcess(container, int(syscall.SIGKILL)); err != nil { // While normally we might "return err" here we're not going to @@ -166,7 +168,7 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error { // Wait for exit with no timeout. // Ignore returned status. - <-container.Wait(context.Background(), containerpkg.WaitConditionNotRunning) + <-container.Wait3(context.Background(), containerpkg.WaitConditionNotRunning, waitStop) return nil } -- 1.8.3.1