diff options
author | Rich Felker <dalias@aerifal.cx> | 2013-11-22 16:29:31 -0500 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2013-11-22 16:29:31 -0500 |
commit | aeea71dc042d8d0a05f4293a0e98c9cd009ffc16 (patch) | |
tree | 4f281963809413f618a9edfa5dfdff813c16031e | |
parent | caaf7d443d8f502a209cb5489c45ddcccbebdd34 (diff) | |
download | musl-aeea71dc042d8d0a05f4293a0e98c9cd009ffc16.tar.gz musl-aeea71dc042d8d0a05f4293a0e98c9cd009ffc16.tar.bz2 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.
-rw-r--r-- | src/misc/wordexp.c | 22 |
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); |