about summary refs log tree commit diff
path: root/src/misc/wordexp.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2013-11-22 16:29:31 -0500
committerRich Felker <dalias@aerifal.cx>2013-11-22 16:29:31 -0500
commitaeea71dc042d8d0a05f4293a0e98c9cd009ffc16 (patch)
tree4f281963809413f618a9edfa5dfdff813c16031e /src/misc/wordexp.c
parentcaaf7d443d8f502a209cb5489c45ddcccbebdd34 (diff)
downloadmusl-aeea71dc042d8d0a05f4293a0e98c9cd009ffc16.tar.gz
musl-aeea71dc042d8d0a05f4293a0e98c9cd009ffc16.tar.xz
musl-aeea71dc042d8d0a05f4293a0e98c9cd009ffc16.zip
fix and refactor child reaping logic in wordexp
loop condition was incorrect and confusing and caused an infinite loop
when (broken) applications reaped the pid from a signal handler or
another thread before wordexp's call to waitpid could do so.
Diffstat (limited to 'src/misc/wordexp.c')
-rw-r--r--src/misc/wordexp.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/misc/wordexp.c b/src/misc/wordexp.c
index 1387b5d2..a5f1b658 100644
--- a/src/misc/wordexp.c
+++ b/src/misc/wordexp.c
@@ -11,6 +11,18 @@
 #include <fcntl.h>
 #include "pthread_impl.h"
 
+static void reap(pid_t pid)
+{
+	int status;
+	for (;;) {
+		if (waitpid(pid, &status, 0) < 0) {
+			if (errno != EINTR) return;
+		} else {
+			if (WIFEXITED(status)) return;
+		}
+	}
+}
+
 static char *getword(FILE *f)
 {
 	char *s = 0;
@@ -24,7 +36,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
 	size_t np=0;
 	char *w, **tmp;
 	char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null";
-	int err = 0, status;
+	int err = 0;
 	FILE *f;
 	size_t wc = 0;
 	char **wv = 0;
@@ -112,7 +124,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
 	if (!f) {
 		close(p[0]);
 		kill(pid, SIGKILL);
-		waitpid(pid, &status, 0);
+		reap(pid);
 		goto nospace;
 	}
 
@@ -121,8 +133,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
 	free(getword(f));
 	if (feof(f)) {
 		fclose(f);
-		while ((waitpid(pid, &status, 0) < 0 && errno == EINTR)
-			|| !WIFEXITED(status));
+		reap(pid);
 		return WRDE_SYNTAX;
 	}
 
@@ -139,8 +150,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
 	if (!feof(f)) err = WRDE_NOSPACE;
 
 	fclose(f);
-	while ((waitpid(pid, &status, 0) < 0 && errno == EINTR)
-		|| !WIFEXITED(status));
+	reap(pid);
 
 	if (!wv) wv = calloc(i+1, sizeof *wv);