From c241f622624fb0849864d68c7048e98f63812b41 Mon Sep 17 00:00:00 2001 From: Petr Skocik Date: Tue, 17 Oct 2017 00:13:43 +0200 Subject: [PATCH 1/3] simplify posix_spawn by avoiding the error pipe --- src/process/posix_spawn.c | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/process/posix_spawn.c b/src/process/posix_spawn.c index ea5d2998..d4377288 100644 --- a/src/process/posix_spawn.c +++ b/src/process/posix_spawn.c @@ -11,7 +11,7 @@ #include "libc.h" struct args { - int p[2]; + volatile int ret; sigset_t oldmask; const char *path; int (*exec)(const char *, char *const *, char *const *); @@ -41,12 +41,10 @@ static int child(void *args_vp) int i, ret; struct sigaction sa = {0}; struct args *args = args_vp; - int p = args->p[1]; const posix_spawn_file_actions_t *fa = args->fa; const posix_spawnattr_t *restrict attr = args->attr; sigset_t hset; - close(args->p[0]); /* All signal dispositions must be either SIG_DFL or SIG_IGN * before signals are unblocked. Otherwise a signal handler @@ -94,16 +92,6 @@ static int child(void *args_vp) int fd; for (op = fa->__actions; op->next; op = op->next); for (; op; op = op->prev) { - /* It's possible that a file operation would clobber - * the pipe fd used for synchronizing with the - * parent. To avoid that, we dup the pipe onto - * an unoccupied fd. */ - if (op->fd == p) { - ret = __syscall(SYS_dup, p); - if (ret < 0) goto fail; - __syscall(SYS_close, p); - p = ret; - } switch(op->cmd) { case FDOP_CLOSE: __syscall(SYS_close, op->fd); @@ -125,12 +113,6 @@ static int child(void *args_vp) } } - /* Close-on-exec flag may have been lost if we moved the pipe - * to a different fd. We don't use F_DUPFD_CLOEXEC above because - * it would fail on older kernels and atomicity is not needed -- - * in this process there are no threads or signal handlers. */ - __syscall(SYS_fcntl, p, F_SETFD, FD_CLOEXEC); - pthread_sigmask(SIG_SETMASK, (attr->__flags & POSIX_SPAWN_SETSIGMASK) ? &attr->__mask : &args->oldmask, 0); @@ -140,7 +122,7 @@ static int child(void *args_vp) fail: /* Since sizeof errno < PIPE_BUF, the write is atomic. */ ret = -ret; - if (ret) while (__syscall(SYS_write, p, &ret, sizeof ret) < 0); + if (ret) args->ret = ret; _exit(127); } @@ -156,9 +138,6 @@ int __posix_spawnx(pid_t *restrict res, const char *restrict path, int ec=0, cs; struct args args; - if (pipe2(args.p, O_CLOEXEC)) - return errno; - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); args.path = path; @@ -171,17 +150,14 @@ int __posix_spawnx(pid_t *restrict res, const char *restrict path, pid = __clone(child, stack+sizeof stack, CLONE_VM|CLONE_VFORK|SIGCHLD, &args); - close(args.p[1]); if (pid > 0) { - if (read(args.p[0], &ec, sizeof ec) != sizeof ec) ec = 0; - else waitpid(pid, &(int){0}, 0); + if (0!=(ec=args.ret)) + waitpid(pid, &(int){0}, 0); } else { ec = -pid; } - close(args.p[0]); - if (!ec && res) *res = pid; pthread_sigmask(SIG_SETMASK, &args.oldmask, 0); -- 2.14.2