From 909ab594191ce964529398bcf7600edff9540d71 Mon Sep 17 00:00:00 2001
From: Valentin Rothberg <rothberg@redhat.com>
Date: Fri, 2 Aug 2019 16:27:50 +0200
Subject: container stop: kill conmon

Old versions of conmon have a bug where they create the exit file before
closing open file descriptors causing a race condition when restarting
containers with open ports since we cannot bind the ports as they're not
yet closed by conmon.

Killing the old conmon PID is ~okay since it forces the FDs of old
conmons to be closed, while it's a NOP for newer versions which should
have exited already.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
---
 libpod/container_internal.go | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

(limited to 'libpod')

diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index aba9c5b93..313f67963 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1152,9 +1152,27 @@ func (c *Container) restartWithTimeout(ctx context.Context, timeout uint) (err e
 	c.newContainerEvent(events.Restart)
 
 	if c.state.State == define.ContainerStateRunning {
+		conmonPID := c.state.ConmonPID
 		if err := c.stop(timeout); err != nil {
 			return err
 		}
+		// Old versions of conmon have a bug where they create the exit file before
+		// closing open file descriptors causing a race condition when restarting
+		// containers with open ports since we cannot bind the ports as they're not
+		// yet closed by conmon.
+		//
+		// Killing the old conmon PID is ~okay since it forces the FDs of old conmons
+		// to be closed, while it's a NOP for newer versions which should have
+		// exited already.
+		if conmonPID != 0 {
+			// Ignore errors from FindProcess() as conmon could already have exited.
+			p, err := os.FindProcess(conmonPID)
+			if p != nil && err == nil {
+				if err = p.Kill(); err != nil {
+					logrus.Debugf("error killing conmon process: %v", err)
+				}
+			}
+		}
 	}
 	defer func() {
 		if err != nil {
-- 
cgit v1.2.3-54-g00ecf