mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
docker kill: fix bug where failed kills didnt fallback to unix kill
1. fixes #41587 2. removes potential infinite Wait and goroutine leak at end of kill function fixes #41587 Signed-off-by: Cam <gh@sparr.email>
This commit is contained in:
@@ -139,29 +139,22 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
|
||||
|
||||
// 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
|
||||
// because if we can't stop the container by this point then
|
||||
// it's probably because it's already stopped. Meaning, between
|
||||
// the time of the IsRunning() call above and now it stopped.
|
||||
// Also, since the err return will be environment specific we can't
|
||||
// look for any particular (common) error that would indicate
|
||||
// that the process is already dead vs something else going wrong.
|
||||
// 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 return it to the caller.
|
||||
// kill failed, check if process is no longer running.
|
||||
if isErrNoSuchProcess(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if status := <-container.Wait(ctx, containerpkg.WaitConditionNotRunning); status.Err() != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Wait for the process to die, in last resort, try to kill the process directly
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
status := <-container.Wait(ctx, containerpkg.WaitConditionNotRunning)
|
||||
if status.Err() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
logrus.WithError(status.Err()).WithField("container", container.ID).Error("Container failed to exit within 10 seconds of kill - trying direct SIGKILL")
|
||||
|
||||
if err := killProcessDirectly(container); err != nil {
|
||||
if isErrNoSuchProcess(err) {
|
||||
return nil
|
||||
@@ -169,10 +162,13 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait for exit with no timeout.
|
||||
// Ignore returned status.
|
||||
<-container.Wait(context.Background(), containerpkg.WaitConditionNotRunning)
|
||||
// wait for container to exit one last time, if it doesn't then kill didnt work, so return error
|
||||
ctx2, cancel2 := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel2()
|
||||
|
||||
if status := <-container.Wait(ctx2, containerpkg.WaitConditionNotRunning); status.Err() != nil {
|
||||
return errors.New("tried to kill container, but did not receive an exit event")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user