|
|
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 */
|