Browse code

Fix stopped containers with restart-policy showing as "restarting"

When manually stopping a container with a restart-policy, the container
would show as "restarting" in `docker ps` whereas its actual state
is "exited".

Stopping a container with a restart policy shows the container as "restarting"

docker run -d --name test --restart unless-stopped busybox false

docker stop test

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e07409fa1d3 busybox "false" 5 minutes ago Restarting (1) 4 minutes ago test

However, inspecting the same container shows that it's exited:

docker inspect test --format '{{ json .State }}'
{
"Status": "exited",
"Running": false,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 0,
"ExitCode": 1,
"Error": "",
"StartedAt": "2019-02-14T13:26:27.6091648Z",
"FinishedAt": "2019-02-14T13:26:27.689427Z"
}

And killing the container confirms this;

docker kill test
Error response from daemon: Cannot kill container: test: Container 7e07409fa1d36dc8d8cb8f25cf12ee1168ad9040183b85fafa73ee2c1fcf9361 is not running

docker run -d --name test --restart unless-stopped busybox false

docker stop test

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d0595237054a busybox "false" 5 minutes ago Restarting (1) 4 minutes ago exit

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2019/02/15 02:59:55
Showing 1 changed files
... ...
@@ -85,6 +85,8 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
85 85
 			}
86 86
 			daemon.LogContainerEventWithAttributes(c, "die", attributes)
87 87
 			daemon.Cleanup(c)
88
+			daemon.setStateCounter(c)
89
+			cpErr := c.CheckpointTo(daemon.containersReplica)
88 90
 
89 91
 			if err == nil && restart {
90 92
 				go func() {
... ...
@@ -101,6 +103,8 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
101 101
 					if err != nil {
102 102
 						c.Lock()
103 103
 						c.SetStopped(&exitStatus)
104
+						daemon.setStateCounter(c)
105
+						c.CheckpointTo(daemon.containersReplica)
104 106
 						c.Unlock()
105 107
 						defer daemon.autoRemove(c)
106 108
 						if err != restartmanager.ErrRestartCanceled {
... ...
@@ -110,8 +114,7 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
110 110
 				}()
111 111
 			}
112 112
 
113
-			daemon.setStateCounter(c)
114
-			return c.CheckpointTo(daemon.containersReplica)
113
+			return cpErr
115 114
 		}
116 115
 
117 116
 		if execConfig := c.ExecCommands.Get(ei.ProcessID); execConfig != nil {