from https://www.mail-archive.com/skaware@list.skarnet.org/msg01006.html diff --git a/src/supervision/s6-supervise.c b/src/supervision/s6-supervise.c index 2e8fa38..7605a82 100644 --- a/src/supervision/s6-supervise.c +++ b/src/supervision/s6-supervise.c @@ -9,6 +9,9 @@ #include #include #include +#ifdef WANT_CLONE_NEWPID +# include +#endif #include #include #include @@ -203,6 +206,67 @@ static int maybesetsid (void) return 1 ; } + static void exec_run(int p[2], int notifyp[2], int fd) gccattr_noreturn ; + static void exec_run(int p[2], int notifyp[2], int fd) + { + char const *cargv[2] = { "run", 0 } ; + PROG = "s6-supervise (child)" ; + selfpipe_finish() ; + if (notifyp[0] >= 0) close(notifyp[0]) ; + close(p[0]) ; + if (notifyp[1] >= 0 && fd_move(fd, notifyp[1]) < 0) + { + failcoe(p[1]) ; + strerr_diefu1sys(127, "move notification descriptor") ; + } + if (!maybesetsid()) + { + failcoe(p[1]) ; + strerr_diefu1sys(127, "access ./nosetsid") ; + } + execve("./run", (char *const *)cargv, (char *const *)environ) ; + failcoe(p[1]) ; + strerr_dieexec(127, "run") ; +} + +static pid_t spawn_run_fork(int p[2], int notifyp[2], int fd) +{ + pid_t pid = fork() ; + if (!pid) exec_run(p, notifyp, fd) ; + return pid ; +} + +#ifdef WANT_CLONE_NEWPID +typedef struct +{ + int p[2] ; + int notifyp[2] ; + int fd ; +} exec_run_t ; + +static int exec_run_shim(void *ctx) gccattr_noreturn ; +static int exec_run_shim(void *ctx) +{ + exec_run_t *er = (exec_run_t *) ctx ; + exec_run(er->p, er->notifyp, er->fd) ; +} + +static pid_t spawn_run(int p[2], int notifyp[2], int fd) +{ + exec_run_t arg = { { p[0], p[1] }, { notifyp[0], notifyp[1] }, fd } ; + char child_stack[SIGSTKSZ] ; + if (access("clone-newpid", F_OK) < 0 && errno == ENOENT) + return spawn_run_fork(p, notifyp, fd) ; + return (pid_t) clone(&exec_run_shim, child_stack + sizeof(child_stack), + CLONE_NEWPID | SIGCHLD, &arg) ; +} +#else /* if !defined(WANT_CLONE_NEWPID) */ +static pid_t spawn_run(int p[2], int notifyp[2], int fd) +{ + return spawn_run_fork(p, notifyp, fd) ; +} +#endif /* defined(WANT_CLONE_NEWPID) */ + static void trystart (void) { int p[2] ; @@ -222,7 +286,7 @@ static void trystart (void) fd_close(p[1]) ; fd_close(p[0]) ; return ; } - pid = fork() ; + pid = spawn_run(p, notifyp, (int)fd) ; if (pid < 0) { settimeout(60) ; @@ -232,27 +296,6 @@ static void trystart (void) fd_close(p[1]) ; fd_close(p[0]) ; return ; } - else if (!pid) - { - char const *cargv[2] = { "run", 0 } ; - PROG = "s6-supervise (child)" ; - selfpipe_finish() ; - if (notifyp[0] >= 0) close(notifyp[0]) ; - close(p[0]) ; - if (notifyp[1] >= 0 && fd_move((int)fd, notifyp[1]) < 0) - { - failcoe(p[1]) ; - strerr_diefu1sys(127, "move notification descriptor") ; - } - if (!maybesetsid()) - { - failcoe(p[1]) ; - strerr_diefu1sys(127, "access ./nosetsid") ; - } - execve("./run", (char *const *)cargv, (char *const *)environ) ; - failcoe(p[1]) ; - strerr_dieexec(127, "run") ; - } if (notifyp[1] >= 0) fd_close(notifyp[1]) ; fd_close(p[1]) ; {