func (daemon *Daemon) shutdownContainer(c *container.Container) error { stopTimeout := c.StopTimeout() // TODO(windows): Handle docker restart with paused containers if c.IsPaused() { // To terminate a process in freezer cgroup, we should send // SIGTERM to this process then unfreeze it, and the process will // force to terminate immediately. logrus.Debugf("Found container %s is paused, sending SIGTERM before unpausing it", c.ID) sig, ok := signal.SignalMap["TERM"] if !ok { return fmt.Errorf("System does not support SIGTERM") } if err := daemon.kill(c, int(sig)); err != nil { return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err) } if err := daemon.containerUnpause(c); err != nil { return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err) } if _, err := c.WaitStop(time.Duration(stopTimeout) * time.Second); err != nil { logrus.Debugf("container %s failed to exit in %d second of SIGTERM, sending SIGKILL to force", c.ID, stopTimeout) sig, ok := signal.SignalMap["KILL"] if !ok { return fmt.Errorf("System does not support SIGKILL") } if err := daemon.kill(c, int(sig)); err != nil { logrus.Errorf("Failed to SIGKILL container %s", c.ID) } c.WaitStop(-1 * time.Second) return err } } // If container failed to exit in stopTimeout seconds of SIGTERM, then using the force if err := daemon.containerStop(c, stopTimeout); err != nil { return fmt.Errorf("Failed to stop container %s with error: %v", c.ID, err) } c.WaitStop(-1 * time.Second) return nil }