dash.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Herbert Xu <herbert@gondor.apana.org.au>
To: dash@vger.kernel.org, Harald van Dijk <harald@gigawatt.nl>
Subject: jobs: Fix infinite loop in waitproc
Date: Fri, 10 Apr 2020 21:03:09 +1000	[thread overview]
Message-ID: <20200410110309.GA13801@gondor.apana.org.au> (raw)

After we changed the resetting of gotsigchld so that it is only
done if jp is NULL, we can now get an infinite loop in waitproc
if gotsigchld is set but there is no outstanding child because
everything had been waited for previously without gotsigchld being
zeroed.

This patch fixes it by always zeroing gotsigchld as we did before.
The bug that the previous patch was trying to fix is now resolved
by switching the blocking mode to DOWAIT_NORMAL after the specified
job has been completed so that we really do wait for all outstanding
dead children.

Reported-by: Harald van Dijk <harald@gigawatt.nl>
Fixes: 6c691b3e5099 ("jobs: Only clear gotsigchld when waiting...")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/src/jobs.c b/src/jobs.c
index 26a6248..72e7aa9 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -1123,15 +1123,28 @@ out:
 
 static int dowait(int block, struct job *jp)
 {
-	int pid = block == DOWAIT_NORMAL ? gotsigchld : 1;
+	int gotchld = *(volatile int *)&gotsigchld;
+	int rpid;
+	int pid;
+
+	if (jp && jp->state != JOBRUNNING)
+		block = DOWAIT_NORMAL;
+
+	if (block == DOWAIT_NORMAL && !gotchld)
+		return 1;
 
-	while (jp ? jp->state == JOBRUNNING : pid > 0) {
-		if (!jp)
-			gotsigchld = 0;
+	rpid = 1;
+
+	do {
+		gotsigchld = 0;
 		pid = waitone(block, jp);
-	}
+		rpid &= !!pid;
 
-	return pid;
+		if (!pid || (jp && jp->state != JOBRUNNING))
+			block = DOWAIT_NORMAL;
+	} while (pid >= 0);
+
+	return rpid;
 }
 
 /*
@@ -1163,7 +1176,10 @@ waitproc(int block, int *status)
 #endif
 
 	do {
-		err = wait3(status, flags, NULL);
+		do
+			err = wait3(status, flags, NULL);
+		while (err < 0 && errno == EINTR);
+
 		if (err || (err = -!block))
 			break;
 
@@ -1173,8 +1189,6 @@ waitproc(int block, int *status)
 			sigsuspend(&oldmask);
 
 		sigclearmask();
-
-		err = 0;
 	} while (gotsigchld);
 
 	return err;
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

                 reply	other threads:[~2020-04-10 11:03 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200410110309.GA13801@gondor.apana.org.au \
    --to=herbert@gondor.apana.org.au \
    --cc=dash@vger.kernel.org \
    --cc=harald@gigawatt.nl \
    --subject='Re: jobs: Fix infinite loop in waitproc' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).