diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lib.h | 7 | ||||
-rw-r--r-- | lib/xwrap.c | 18 |
2 files changed, 17 insertions, 8 deletions
@@ -98,6 +98,7 @@ void xputc(char c); void xflush(void); void xexec(char **argv); pid_t xpopen_both(char **argv, int *pipes); +int xwaitpid(pid_t pid); int xpclose_both(pid_t pid, int *pipes); pid_t xpopen(char **argv, int *pipe, int stdout); pid_t xpclose(pid_t pid, int pipe); @@ -248,12 +249,12 @@ void names_to_pid(char **names, int (*callback)(pid_t pid, char *name)); // Returning from a function can modify a potentially shared stack, // so this has to always inline. - static inline pid_t xvfork(void) { - pid_t p = vfork(); + pid_t p; - if (p == -1) perror_exit("vfork"); + toys.stacktop = 0; + if ((p = vfork()) == -1) perror_exit("vfork"); return p; } diff --git a/lib/xwrap.c b/lib/xwrap.c index 80862828..e5dc4826 100644 --- a/lib/xwrap.c +++ b/lib/xwrap.c @@ -133,7 +133,8 @@ void xflush(void) // with a path isn't a builtin, so /bin/sh won't match the builtin sh. void xexec(char **argv) { - if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE) toy_exec(argv); + // Only recurse to builtin when we have multiplexer and !vfork context. + if (CFG_TOYBOX && !CFG_TOYBOX_NORECURSE && toys.stacktop) toy_exec(argv); execvp(argv[0], argv); perror_msg("exec %s", argv[0]); @@ -198,17 +199,24 @@ pid_t xpopen_both(char **argv, int *pipes) return pid; } -int xpclose_both(pid_t pid, int *pipes) +// Wait for child process to exit, then return adjusted exit code. +int xwaitpid(pid_t pid) { - int rc = 127; + int status; + + while (-1 == waitpid(pid, &status, 0) && errno == EINTR); + + return WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127; +} +int xpclose_both(pid_t pid, int *pipes) +{ if (pipes) { close(pipes[0]); close(pipes[1]); } - waitpid(pid, &rc, 0); - return WIFEXITED(rc) ? WEXITSTATUS(rc) : WTERMSIG(rc) + 127; + return xwaitpid(pid); } // Wrapper to xpopen with a pipe for just one of stdin/stdout |