瀏覽代碼

libcontainerd: wait for restart after state change

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
(cherry picked from commit 495448b2903c1a765cc17dff05afebe16a466917)
Signed-off-by: Tibor Vass <tibor@docker.com>
Tonis Tiigi 9 年之前
父節點
當前提交
f6d388f5b1
共有 2 個文件被更改,包括 38 次插入29 次删除
  1. 20 15
      libcontainerd/container_linux.go
  2. 18 14
      libcontainerd/container_windows.go

+ 20 - 15
libcontainerd/container_linux.go

@@ -144,6 +144,7 @@ func (ctr *container) handleEvent(e *containerd.Event) error {
 	defer ctr.client.unlock(ctr.containerID)
 	defer ctr.client.unlock(ctr.containerID)
 	switch e.Type {
 	switch e.Type {
 	case StateExit, StatePause, StateResume, StateOOM:
 	case StateExit, StatePause, StateResume, StateOOM:
+		var waitRestart chan error
 		st := StateInfo{
 		st := StateInfo{
 			CommonStateInfo: CommonStateInfo{
 			CommonStateInfo: CommonStateInfo{
 				State:    e.Type,
 				State:    e.Type,
@@ -166,8 +167,26 @@ func (ctr *container) handleEvent(e *containerd.Event) error {
 				st.State = StateRestart
 				st.State = StateRestart
 				ctr.restarting = true
 				ctr.restarting = true
 				ctr.client.deleteContainer(e.Id)
 				ctr.client.deleteContainer(e.Id)
+				waitRestart = wait
+			}
+		}
+
+		// Remove process from list if we have exited
+		// We need to do so here in case the Message Handler decides to restart it.
+		switch st.State {
+		case StateExit:
+			ctr.clean()
+			ctr.client.deleteContainer(e.Id)
+		case StateExitProcess:
+			ctr.cleanProcess(st.ProcessID)
+		}
+		ctr.client.q.append(e.Id, func() {
+			if err := ctr.client.backend.StateChanged(e.Id, st); err != nil {
+				logrus.Errorf("libcontainerd: backend.StateChanged(): %v", err)
+			}
+			if st.State == StateRestart {
 				go func() {
 				go func() {
-					err := <-wait
+					err := <-waitRestart
 					ctr.client.lock(ctr.containerID)
 					ctr.client.lock(ctr.containerID)
 					defer ctr.client.unlock(ctr.containerID)
 					defer ctr.client.unlock(ctr.containerID)
 					ctr.restarting = false
 					ctr.restarting = false
@@ -187,21 +206,7 @@ func (ctr *container) handleEvent(e *containerd.Event) error {
 					}
 					}
 				}()
 				}()
 			}
 			}
-		}
 
 
-		// Remove process from list if we have exited
-		// We need to do so here in case the Message Handler decides to restart it.
-		switch st.State {
-		case StateExit:
-			ctr.clean()
-			ctr.client.deleteContainer(e.Id)
-		case StateExitProcess:
-			ctr.cleanProcess(st.ProcessID)
-		}
-		ctr.client.q.append(e.Id, func() {
-			if err := ctr.client.backend.StateChanged(e.Id, st); err != nil {
-				logrus.Errorf("libcontainerd: backend.StateChanged(): %v", err)
-			}
 			if e.Type == StatePause || e.Type == StateResume {
 			if e.Type == StatePause || e.Type == StateResume {
 				ctr.pauseMonitor.handle(e.Type)
 				ctr.pauseMonitor.handle(e.Type)
 			}
 			}

+ 18 - 14
libcontainerd/container_windows.go

@@ -191,6 +191,7 @@ func (ctr *container) waitProcessExitCode(process *process) int {
 // equivalent to (in the linux containerd world) where events come in for
 // equivalent to (in the linux containerd world) where events come in for
 // state change notifications from containerd.
 // state change notifications from containerd.
 func (ctr *container) waitExit(process *process, isFirstProcessToStart bool) error {
 func (ctr *container) waitExit(process *process, isFirstProcessToStart bool) error {
+	var waitRestart chan error
 	logrus.Debugln("libcontainerd: waitExit() on pid", process.systemPid)
 	logrus.Debugln("libcontainerd: waitExit() on pid", process.systemPid)
 
 
 	exitCode := ctr.waitProcessExitCode(process)
 	exitCode := ctr.waitProcessExitCode(process)
@@ -234,20 +235,7 @@ func (ctr *container) waitExit(process *process, isFirstProcessToStart bool) err
 			} else if restart {
 			} else if restart {
 				si.State = StateRestart
 				si.State = StateRestart
 				ctr.restarting = true
 				ctr.restarting = true
-				go func() {
-					err := <-wait
-					ctr.restarting = false
-					ctr.client.deleteContainer(ctr.friendlyName)
-					if err != nil {
-						si.State = StateExit
-						if err := ctr.client.backend.StateChanged(ctr.containerID, si); err != nil {
-							logrus.Error(err)
-						}
-						logrus.Error(err)
-					} else {
-						ctr.client.Create(ctr.containerID, ctr.ociSpec, ctr.options...)
-					}
-				}()
+				waitRestart = wait
 			}
 			}
 		}
 		}
 
 
@@ -263,6 +251,22 @@ func (ctr *container) waitExit(process *process, isFirstProcessToStart bool) err
 	if err := ctr.client.backend.StateChanged(ctr.containerID, si); err != nil {
 	if err := ctr.client.backend.StateChanged(ctr.containerID, si); err != nil {
 		logrus.Error(err)
 		logrus.Error(err)
 	}
 	}
+	if si.State == StateRestart {
+		go func() {
+			err := <-waitRestart
+			ctr.restarting = false
+			ctr.client.deleteContainer(ctr.friendlyName)
+			if err != nil {
+				si.State = StateExit
+				if err := ctr.client.backend.StateChanged(ctr.containerID, si); err != nil {
+					logrus.Error(err)
+				}
+				logrus.Error(err)
+			} else {
+				ctr.client.Create(ctr.containerID, ctr.ociSpec, ctr.options...)
+			}
+		}()
+	}
 
 
 	logrus.Debugf("libcontainerd: waitExit() completed OK, %+v", si)
 	logrus.Debugf("libcontainerd: waitExit() completed OK, %+v", si)
 	return nil
 	return nil