Refactor Shutdown a little to reduce indentation
| ... | ... |
@@ -830,6 +830,45 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo |
| 830 | 830 |
return d, nil |
| 831 | 831 |
} |
| 832 | 832 |
|
| 833 |
+func stopContainer(c *Container) error {
|
|
| 834 |
+ // TODO(windows): Handle docker restart with paused containers |
|
| 835 |
+ if c.isPaused() {
|
|
| 836 |
+ // To terminate a process in freezer cgroup, we should send |
|
| 837 |
+ // SIGTERM to this process then unfreeze it, and the process will |
|
| 838 |
+ // force to terminate immediately. |
|
| 839 |
+ logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID)
|
|
| 840 |
+ sig, ok := signal.SignalMap["TERM"] |
|
| 841 |
+ if !ok {
|
|
| 842 |
+ return fmt.Errorf("System doesn not support SIGTERM")
|
|
| 843 |
+ } |
|
| 844 |
+ if err := c.daemon.kill(c, int(sig)); err != nil {
|
|
| 845 |
+ return fmt.Errorf("sending SIGTERM to container %s with error: %v", c.ID, err)
|
|
| 846 |
+ } |
|
| 847 |
+ if err := c.unpause(); err != nil {
|
|
| 848 |
+ return fmt.Errorf("Failed to unpause container %s with error: %v", c.ID, err)
|
|
| 849 |
+ } |
|
| 850 |
+ if _, err := c.WaitStop(10 * time.Second); err != nil {
|
|
| 851 |
+ logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID)
|
|
| 852 |
+ sig, ok := signal.SignalMap["KILL"] |
|
| 853 |
+ if !ok {
|
|
| 854 |
+ return fmt.Errorf("System does not support SIGKILL")
|
|
| 855 |
+ } |
|
| 856 |
+ if err := c.daemon.kill(c, int(sig)); err != nil {
|
|
| 857 |
+ logrus.Errorf("Failed to SIGKILL container %s", c.ID)
|
|
| 858 |
+ } |
|
| 859 |
+ c.WaitStop(-1 * time.Second) |
|
| 860 |
+ return err |
|
| 861 |
+ } |
|
| 862 |
+ } |
|
| 863 |
+ // If container failed to exit in 10 seconds of SIGTERM, then using the force |
|
| 864 |
+ if err := c.Stop(10); err != nil {
|
|
| 865 |
+ return fmt.Errorf("Stop container %s with error: %v", c.ID, err)
|
|
| 866 |
+ } |
|
| 867 |
+ |
|
| 868 |
+ c.WaitStop(-1 * time.Second) |
|
| 869 |
+ return nil |
|
| 870 |
+} |
|
| 871 |
+ |
|
| 833 | 872 |
// Shutdown stops the daemon. |
| 834 | 873 |
func (daemon *Daemon) Shutdown() error {
|
| 835 | 874 |
daemon.shutdown = true |
| ... | ... |
@@ -837,58 +876,26 @@ func (daemon *Daemon) Shutdown() error {
|
| 837 | 837 |
group := sync.WaitGroup{}
|
| 838 | 838 |
logrus.Debug("starting clean shutdown of all containers...")
|
| 839 | 839 |
for _, container := range daemon.List() {
|
| 840 |
- c := container |
|
| 841 |
- if c.IsRunning() {
|
|
| 842 |
- logrus.Debugf("stopping %s", c.ID)
|
|
| 843 |
- group.Add(1) |
|
| 844 |
- |
|
| 845 |
- go func() {
|
|
| 846 |
- defer group.Done() |
|
| 847 |
- // TODO(windows): Handle docker restart with paused containers |
|
| 848 |
- if c.isPaused() {
|
|
| 849 |
- // To terminate a process in freezer cgroup, we should send |
|
| 850 |
- // SIGTERM to this process then unfreeze it, and the process will |
|
| 851 |
- // force to terminate immediately. |
|
| 852 |
- logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID)
|
|
| 853 |
- sig, ok := signal.SignalMap["TERM"] |
|
| 854 |
- if !ok {
|
|
| 855 |
- logrus.Warnf("System does not support SIGTERM")
|
|
| 856 |
- return |
|
| 857 |
- } |
|
| 858 |
- if err := daemon.kill(c, int(sig)); err != nil {
|
|
| 859 |
- logrus.Debugf("sending SIGTERM to container %s with error: %v", c.ID, err)
|
|
| 860 |
- return |
|
| 861 |
- } |
|
| 862 |
- if err := c.unpause(); err != nil {
|
|
| 863 |
- logrus.Debugf("Failed to unpause container %s with error: %v", c.ID, err)
|
|
| 864 |
- return |
|
| 865 |
- } |
|
| 866 |
- if _, err := c.WaitStop(10 * time.Second); err != nil {
|
|
| 867 |
- logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID)
|
|
| 868 |
- sig, ok := signal.SignalMap["KILL"] |
|
| 869 |
- if !ok {
|
|
| 870 |
- logrus.Warnf("System does not support SIGKILL")
|
|
| 871 |
- return |
|
| 872 |
- } |
|
| 873 |
- daemon.kill(c, int(sig)) |
|
| 874 |
- } |
|
| 875 |
- } else {
|
|
| 876 |
- // If container failed to exit in 10 seconds of SIGTERM, then using the force |
|
| 877 |
- if err := c.Stop(10); err != nil {
|
|
| 878 |
- logrus.Errorf("Stop container %s with error: %v", c.ID, err)
|
|
| 879 |
- } |
|
| 880 |
- } |
|
| 881 |
- c.WaitStop(-1 * time.Second) |
|
| 882 |
- logrus.Debugf("container stopped %s", c.ID)
|
|
| 883 |
- }() |
|
| 840 |
+ if !container.IsRunning() {
|
|
| 841 |
+ continue |
|
| 884 | 842 |
} |
| 843 |
+ logrus.Debugf("stopping %s", container.ID)
|
|
| 844 |
+ group.Add(1) |
|
| 845 |
+ go func(c *Container) {
|
|
| 846 |
+ defer group.Done() |
|
| 847 |
+ if err := stopContainer(c); err != nil {
|
|
| 848 |
+ logrus.Errorf("Stop container error: %v", err)
|
|
| 849 |
+ return |
|
| 850 |
+ } |
|
| 851 |
+ logrus.Debugf("container stopped %s", c.ID)
|
|
| 852 |
+ }(container) |
|
| 885 | 853 |
} |
| 886 | 854 |
group.Wait() |
| 855 |
+ } |
|
| 887 | 856 |
|
| 888 |
- // trigger libnetwork Stop only if it's initialized |
|
| 889 |
- if daemon.netController != nil {
|
|
| 890 |
- daemon.netController.Stop() |
|
| 891 |
- } |
|
| 857 |
+ // trigger libnetwork Stop only if it's initialized |
|
| 858 |
+ if daemon.netController != nil {
|
|
| 859 |
+ daemon.netController.Stop() |
|
| 892 | 860 |
} |
| 893 | 861 |
|
| 894 | 862 |
if daemon.containerGraphDB != nil {
|