Blame SOURCES/0738-avoid-possible-hang-if-our-child-process-hangs.patch

17b0f1
From 64d0115dcda445a5b1c069f696a363730f654425 Mon Sep 17 00:00:00 2001
17b0f1
From: David Tardon <dtardon@redhat.com>
17b0f1
Date: Thu, 2 May 2019 12:55:04 +0200
17b0f1
Subject: [PATCH] avoid possible hang if our child process hangs
17b0f1
17b0f1
If there is one or more unexpected child processes that terminate, but
17b0f1
the "main" child process hangs, we will loop through the terminated
17b0f1
children and then, eventually, get stuck in the waitpid() call. Let's
17b0f1
repeat the main cycle if that situation happens, as that allows us to
17b0f1
finish after timeout.
17b0f1
17b0f1
Related: #1697909
17b0f1
---
17b0f1
 src/udev/udev-event.c | 11 +++++++++--
17b0f1
 1 file changed, 9 insertions(+), 2 deletions(-)
17b0f1
17b0f1
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
17b0f1
index 5550ec93de..79b8614ec2 100644
17b0f1
--- a/src/udev/udev-event.c
17b0f1
+++ b/src/udev/udev-event.c
17b0f1
@@ -605,6 +605,7 @@ static int spawn_wait(struct udev_event *event,
17b0f1
                         struct signalfd_siginfo fdsi;
17b0f1
                         int status, r;
17b0f1
                         ssize_t size;
17b0f1
+                        bool wait_again = false;
17b0f1
 
17b0f1
                         size = read(event->fd_signal, &fdsi, sizeof(struct signalfd_siginfo));
17b0f1
                         if (size != sizeof(struct signalfd_siginfo))
17b0f1
@@ -622,15 +623,21 @@ static int spawn_wait(struct udev_event *event,
17b0f1
                                            In case the PID we wait for also exited the kernel could coalesce SIGCHLDs and we won't get second SIGCHLD
17b0f1
                                            on the signalfd. We can't know if coalescing happened or not, hence we need to call waitpid() in a loop until
17b0f1
                                            the PID we care for exits, we if it haven't already. */
17b0f1
-                                        while (child_exited < 0) {
17b0f1
-                                                r = waitpid(-1, &status, 0);
17b0f1
+                                        while (child_exited < 0 && !wait_again) {
17b0f1
+                                                r = waitpid(-1, &status, WNOHANG);
17b0f1
                                                 if (r < 0 && errno == EINTR)
17b0f1
                                                         continue;
17b0f1
                                                 else if (r < 0)
17b0f1
                                                         break;
17b0f1
                                                 else if (r == pid)
17b0f1
                                                         child_exited = 0;
17b0f1
+                                                else if (r == 0)
17b0f1
+                                                        wait_again = true;
17b0f1
                                         }
17b0f1
+
17b0f1
+                                        /* Only unexpected process(es) have been terminated. Continue waiting */
17b0f1
+                                        if (wait_again)
17b0f1
+                                                continue;
17b0f1
                                 }
17b0f1
 
17b0f1
                                 /* We didn't wait for child yet, let's do that now */