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 /src | |
| parent | caaf7d443d8f502a209cb5489c45ddcccbebdd34 (diff) | |
| download | musl-aeea71dc042d8d0a05f4293a0e98c9cd009ffc16.tar.gz | |
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')
| -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); | 
