|
@@ -139,29 +139,22 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
|
|
|
|
|
|
// 1. Send SIGKILL
|
|
// 1. Send SIGKILL
|
|
if err := daemon.killPossiblyDeadProcess(container, int(syscall.SIGKILL)); err != nil {
|
|
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) {
|
|
if isErrNoSuchProcess(err) {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
- ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
|
|
- defer cancel()
|
|
|
|
|
|
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
+ defer cancel()
|
|
|
|
|
|
- if status := <-container.Wait(ctx, containerpkg.WaitConditionNotRunning); status.Err() != nil {
|
|
|
|
- return err
|
|
|
|
- }
|
|
|
|
|
|
+ status := <-container.Wait(ctx, containerpkg.WaitConditionNotRunning)
|
|
|
|
+ if status.Err() == nil {
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
|
|
- // 2. Wait for the process to die, in last resort, try to kill the process directly
|
|
|
|
|
|
+ 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 err := killProcessDirectly(container); err != nil {
|
|
if isErrNoSuchProcess(err) {
|
|
if isErrNoSuchProcess(err) {
|
|
return nil
|
|
return nil
|
|
@@ -169,10 +162,13 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
|
|
return err
|
|
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
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|