From 11c5aacb08ce5bdbccf81e056fd61facb3097c9b Mon Sep 17 00:00:00 2001 From: nick black Date: Tue, 21 Apr 2020 09:42:25 -0400 Subject: [PATCH] ncsubproc: move to big bad clone3() #310 --- README.md | 1 + src/lib/fd.c | 25 +++++++++++++++++++------ src/lib/internal.h | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4a969028e..49bf6506c 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ that fine library. * (OPTIONAL) (documentation) [pandoc](https://pandoc.org/index.html) 1.19.2+ * (OPTIONAL) (python bindings): Python 3.7+, [CFFI](https://pypi.org/project/cffi/) 1.13.2+ * (OPTIONAL) (rust bindings): rust 1.40.0+, cargo 0.40.0+, [bindgen](https://crates.io/crates/bindgen) 0.53.0+ +* (runtime) Linux 5.3+ ### Building diff --git a/src/lib/fd.c b/src/lib/fd.c index 6cd809808..9190531e1 100644 --- a/src/lib/fd.c +++ b/src/lib/fd.c @@ -1,7 +1,9 @@ #include #include +#include #include #include +#include #include "internal.h" // release the memory and fd, but don't join the thread (since we might be @@ -90,12 +92,24 @@ int ncfdplane_destroy(ncfdplane* n){ } static pid_t -launch_pipe_process(int* pipe){ +launch_pipe_process(int* pipe, int* pidfd){ int pipes[2]; if(pipe2(pipes, O_CLOEXEC)){ return -1; } - pid_t p = fork(); + struct clone_args clargs = { + .flags = CLONE_CLEAR_SIGHAND | CLONE_FS | CLONE_PIDFD, + .pidfd = (uintptr_t)pidfd, + .child_tid = 0, // FIXME + .parent_tid = 0, // FIXME + .exit_signal = SIGCHLD, // FIXME maybe switch it up for doctest? + .stack = 0, // automatically created by clone3() + .stack_size = 0, // automatically set by clone3() + .tls = 0, // FIXME + .set_tid = 0, // FIXME + .set_tid_size = 0, // FIXME + }; + pid_t p = syscall(__NR_clone3, &clargs, sizeof(clargs)); if(p == 0){ if(dup2(pipes[1], STDOUT_FILENO) < 0 || dup2(pipes[1], STDERR_FILENO) < 0){ return -1; @@ -143,7 +157,6 @@ ncsubproc_thread(void* vncsp){ static ncfdplane* ncsubproc_launch(ncplane* n, ncsubproc* ret, const ncsubproc_options* opts, int fd, ncfdplane_callback cbfxn, ncfdplane_done_cb donecbfxn){ - // FIXME need to pick up pidfd via clone() earlier in launch_pipe_process ret->nfp = ncfdplane_create_internal(n, &opts->popts, fd, cbfxn, donecbfxn, false); if(ret->nfp == NULL){ return NULL; @@ -166,7 +179,7 @@ ncsubproc* ncsubproc_createv(ncplane* n, const ncsubproc_options* opts, if(ret == NULL){ return NULL; } - ret->pid = launch_pipe_process(&fd); + ret->pid = launch_pipe_process(&fd, &ret->pidfd); if(ret->pid == 0){ execv(bin, arg); fprintf(stderr, "Error execv()ing %s\n", bin); @@ -194,7 +207,7 @@ ncsubproc* ncsubproc_createvp(ncplane* n, const ncsubproc_options* opts, if(ret == NULL){ return NULL; } - ret->pid = launch_pipe_process(&fd); + ret->pid = launch_pipe_process(&fd, &ret->pidfd); if(ret->pid == 0){ execvp(bin, arg); fprintf(stderr, "Error execv()ing %s\n", bin); @@ -222,7 +235,7 @@ ncsubproc* ncsubproc_createvpe(ncplane* n, const ncsubproc_options* opts, if(ret == NULL){ return NULL; } - ret->pid = launch_pipe_process(&fd); + ret->pid = launch_pipe_process(&fd, &ret->pidfd); if(ret->pid == 0){ #ifdef __FreeBSD__ exect(bin, arg, env); diff --git a/src/lib/internal.h b/src/lib/internal.h index e0b537ef9..9e5c40071 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -201,6 +201,7 @@ typedef struct ncfdplane { typedef struct ncsubproc { ncfdplane* nfp; pid_t pid; // subprocess + int pidfd; // for signaling/watching the subprocess } ncsubproc; typedef struct ncmenu {