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.
This commit is contained in:
parent
caaf7d443d
commit
aeea71dc04
1 changed files with 16 additions and 6 deletions
|
|
@ -11,6 +11,18 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "pthread_impl.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)
|
static char *getword(FILE *f)
|
||||||
{
|
{
|
||||||
char *s = 0;
|
char *s = 0;
|
||||||
|
|
@ -24,7 +36,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
|
||||||
size_t np=0;
|
size_t np=0;
|
||||||
char *w, **tmp;
|
char *w, **tmp;
|
||||||
char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null";
|
char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null";
|
||||||
int err = 0, status;
|
int err = 0;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
size_t wc = 0;
|
size_t wc = 0;
|
||||||
char **wv = 0;
|
char **wv = 0;
|
||||||
|
|
@ -112,7 +124,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
|
||||||
if (!f) {
|
if (!f) {
|
||||||
close(p[0]);
|
close(p[0]);
|
||||||
kill(pid, SIGKILL);
|
kill(pid, SIGKILL);
|
||||||
waitpid(pid, &status, 0);
|
reap(pid);
|
||||||
goto nospace;
|
goto nospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,8 +133,7 @@ static int do_wordexp(const char *s, wordexp_t *we, int flags)
|
||||||
free(getword(f));
|
free(getword(f));
|
||||||
if (feof(f)) {
|
if (feof(f)) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
while ((waitpid(pid, &status, 0) < 0 && errno == EINTR)
|
reap(pid);
|
||||||
|| !WIFEXITED(status));
|
|
||||||
return WRDE_SYNTAX;
|
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;
|
if (!feof(f)) err = WRDE_NOSPACE;
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
while ((waitpid(pid, &status, 0) < 0 && errno == EINTR)
|
reap(pid);
|
||||||
|| !WIFEXITED(status));
|
|
||||||
|
|
||||||
if (!wv) wv = calloc(i+1, sizeof *wv);
|
if (!wv) wv = calloc(i+1, sizeof *wv);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue