File pacemaker-libservices-no-zombie-left.patch of Package pacemaker.14737
commit 142169da59518ee17bbf885dfbf42525fd2c1d0b
Author: Jan Pokorný <jpokorny@redhat.com>
Date: Tue Jan 31 20:06:21 2017 +0100
Low: libservices (sync): ensure no zombie is left behind
It could happen because this parent that is to wait for its
not-well-behaved child is knowlingly not blocking any signal (beside
SIGCHLD explicitly in case of using signalfd facility) and delivery of
such signal can interrupt waitpid, at least on paper, so protect
against this accordingly.
Speaking of SIGCHLD in plain self-pipe (not signalfd one) context, while
there's no clash with other synchronous actions, it may be the case with
asynchronous ones (or for that matter, arbitrary other fork-related
activities in the main program a library can have no idea about), and
this is exactly what could interrupt waitpid for real.
diff --git a/lib/services/services_linux.c b/lib/services/services_linux.c
index cd7fd3f21..ffb74ef42 100644
--- a/lib/services/services_linux.c
+++ b/lib/services/services_linux.c
@@ -517,7 +517,7 @@ action_synced_wait(svc_action_t * op, sigset_t *mask)
if (1) {
/* Clear out the sigchld pipe. */
char ch;
- while (read(sfd, &ch, 1) == 1);
+ while (read(sfd, &ch, 1) == 1) /*omit*/;
#endif
wait_rc = waitpid(op->pid, &status, WNOHANG);
@@ -567,7 +567,7 @@ action_synced_wait(svc_action_t * op, sigset_t *mask)
*
* This makes it safe to skip WNOHANG here
*/
- waitpid(op->pid, &status, 0);
+ while (waitpid(op->pid, &status, 0) == (pid_t) -1 && errno == EINTR) /*omit*/;
} else if (WIFEXITED(status)) {
op->status = PCMK_LRM_OP_DONE;