From aeea71dc042d8d0a05f4293a0e98c9cd009ffc16 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Fri, 22 Nov 2013 16:29:31 -0500 Subject: 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. --- src/misc/wordexp.c | 22 ++++++++++++++++------ 1 file 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 #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); -- cgit v1.2.1