Fix restart docker daemon with paused containers
| ... | ... |
@@ -31,6 +31,7 @@ import ( |
| 31 | 31 |
"github.com/docker/docker/pkg/ioutils" |
| 32 | 32 |
"github.com/docker/docker/pkg/namesgenerator" |
| 33 | 33 |
"github.com/docker/docker/pkg/nat" |
| 34 |
+ "github.com/docker/docker/pkg/signal" |
|
| 34 | 35 |
"github.com/docker/docker/pkg/stringid" |
| 35 | 36 |
"github.com/docker/docker/pkg/sysinfo" |
| 36 | 37 |
"github.com/docker/docker/pkg/system" |
| ... | ... |
@@ -766,9 +767,39 @@ func (daemon *Daemon) Shutdown() error {
|
| 766 | 766 |
|
| 767 | 767 |
go func() {
|
| 768 | 768 |
defer group.Done() |
| 769 |
- // If container failed to exit in 10 seconds of SIGTERM, then using the force |
|
| 770 |
- if err := c.Stop(10); err != nil {
|
|
| 771 |
- logrus.Errorf("Stop container %s with error: %v", c.ID, err)
|
|
| 769 |
+ // TODO(windows): Handle docker restart with paused containers |
|
| 770 |
+ if c.IsPaused() {
|
|
| 771 |
+ // To terminate a process in freezer cgroup, we should send |
|
| 772 |
+ // SIGTERM to this process then unfreeze it, and the process will |
|
| 773 |
+ // force to terminate immediately. |
|
| 774 |
+ logrus.Debugf("Found container %s is paused, sending SIGTERM before unpause it", c.ID)
|
|
| 775 |
+ sig, ok := signal.SignalMap["TERM"] |
|
| 776 |
+ if !ok {
|
|
| 777 |
+ logrus.Warnf("System does not support SIGTERM")
|
|
| 778 |
+ return |
|
| 779 |
+ } |
|
| 780 |
+ if err := daemon.Kill(c, int(sig)); err != nil {
|
|
| 781 |
+ logrus.Debugf("sending SIGTERM to container %s with error: %v", c.ID, err)
|
|
| 782 |
+ return |
|
| 783 |
+ } |
|
| 784 |
+ if err := c.Unpause(); err != nil {
|
|
| 785 |
+ logrus.Debugf("Failed to unpause container %s with error: %v", c.ID, err)
|
|
| 786 |
+ return |
|
| 787 |
+ } |
|
| 788 |
+ if _, err := c.WaitStop(10 * time.Second); err != nil {
|
|
| 789 |
+ logrus.Debugf("container %s failed to exit in 10 second of SIGTERM, sending SIGKILL to force", c.ID)
|
|
| 790 |
+ sig, ok := signal.SignalMap["KILL"] |
|
| 791 |
+ if !ok {
|
|
| 792 |
+ logrus.Warnf("System does not support SIGKILL")
|
|
| 793 |
+ return |
|
| 794 |
+ } |
|
| 795 |
+ daemon.Kill(c, int(sig)) |
|
| 796 |
+ } |
|
| 797 |
+ } else {
|
|
| 798 |
+ // If container failed to exit in 10 seconds of SIGTERM, then using the force |
|
| 799 |
+ if err := c.Stop(10); err != nil {
|
|
| 800 |
+ logrus.Errorf("Stop container %s with error: %v", c.ID, err)
|
|
| 801 |
+ } |
|
| 772 | 802 |
} |
| 773 | 803 |
c.WaitStop(-1 * time.Second) |
| 774 | 804 |
logrus.Debugf("container stopped %s", c.ID)
|
| ... | ... |
@@ -1624,3 +1624,41 @@ func (s *DockerDaemonSuite) TestDaemonWideLogConfig(c *check.C) {
|
| 1624 | 1624 |
c.Fatalf("Unexpected log-opt: %s, expected map[max-size:1k]", cfg)
|
| 1625 | 1625 |
} |
| 1626 | 1626 |
} |
| 1627 |
+ |
|
| 1628 |
+func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) {
|
|
| 1629 |
+ if err := s.d.StartWithBusybox(); err != nil {
|
|
| 1630 |
+ c.Fatal(err) |
|
| 1631 |
+ } |
|
| 1632 |
+ if out, err := s.d.Cmd("run", "-i", "-d", "--name", "test", "busybox", "top"); err != nil {
|
|
| 1633 |
+ c.Fatal(err, out) |
|
| 1634 |
+ } |
|
| 1635 |
+ if out, err := s.d.Cmd("pause", "test"); err != nil {
|
|
| 1636 |
+ c.Fatal(err, out) |
|
| 1637 |
+ } |
|
| 1638 |
+ if err := s.d.Restart(); err != nil {
|
|
| 1639 |
+ c.Fatal(err) |
|
| 1640 |
+ } |
|
| 1641 |
+ |
|
| 1642 |
+ errchan := make(chan error) |
|
| 1643 |
+ go func() {
|
|
| 1644 |
+ out, err := s.d.Cmd("start", "test")
|
|
| 1645 |
+ if err != nil {
|
|
| 1646 |
+ errchan <- fmt.Errorf("%v:\n%s", err, out)
|
|
| 1647 |
+ } |
|
| 1648 |
+ name := strings.TrimSpace(out) |
|
| 1649 |
+ if name != "test" {
|
|
| 1650 |
+ errchan <- fmt.Errorf("Paused container start error on docker daemon restart, expected 'test' but got '%s'", name)
|
|
| 1651 |
+ } |
|
| 1652 |
+ close(errchan) |
|
| 1653 |
+ }() |
|
| 1654 |
+ |
|
| 1655 |
+ select {
|
|
| 1656 |
+ case <-time.After(5 * time.Second): |
|
| 1657 |
+ c.Fatal("Waiting on start a container timed out")
|
|
| 1658 |
+ case err := <-errchan: |
|
| 1659 |
+ if err != nil {
|
|
| 1660 |
+ c.Fatal(err) |
|
| 1661 |
+ } |
|
| 1662 |
+ } |
|
| 1663 |
+ |
|
| 1664 |
+} |