diff --git a/src/lib/fd.c b/src/lib/fd.c index 00eb4acd7..d111911bd 100644 --- a/src/lib/fd.c +++ b/src/lib/fd.c @@ -150,6 +150,9 @@ launch_pipe_process(int* pipe, int* pidfd){ if(pipe2(pipes, O_CLOEXEC)){ // can't use O_NBLOCK here (affects client) return -1; } + pid_t p = -1; + // on linux, we try to use the brand-new pidfd capability via clone3(). if + // that fails, fall through to fork(), which is all we try to use on freebsd. #ifdef __linux__ // FIXME introduced in linux 5.5 #ifndef CLONE_CLEAR_SIGHAND @@ -159,11 +162,12 @@ launch_pipe_process(int* pipe, int* pidfd){ memset(&clargs, 0, sizeof(clargs)); clargs.pidfd = (uintptr_t)pidfd; clargs.flags = CLONE_CLEAR_SIGHAND | CLONE_FS | CLONE_PIDFD; - pid_t p = syscall(__NR_clone3, &clargs, sizeof(clargs)); + p = syscall(__NR_clone3, &clargs, sizeof(clargs)); #else - (void)pidfd; - pid_t p = fork(); #endif + if(p < 0){ + p = fork(); + } if(p == 0){ // child if(dup2(pipes[1], STDOUT_FILENO) < 0 || dup2(pipes[1], STDERR_FILENO) < 0){ fprintf(stderr, "Couldn't dup() %d (%s)\n", pipes[1], strerror(errno)); @@ -181,15 +185,20 @@ launch_pipe_process(int* pipe, int* pidfd){ // FIXME rigourize and port this static int kill_and_wait_subproc(pid_t pid, int pidfd, int* status){ + int ret = -1; + // on linux, we try pidfd_send_signal, if the pidfd has been defined. + // otherwise, we fall back to regular old kill(); + if(pidfd >= 0){ #ifdef __linux__ - syscall(__NR_pidfd_send_signal, pidfd, SIGKILL, NULL, 0); - siginfo_t info; - memset(&info, 0, sizeof(info)); - waitid(P_PIDFD, pidfd, &info, 0); -#else - (void)pidfd; - kill(pid, SIGKILL); + ret = syscall(__NR_pidfd_send_signal, pidfd, SIGKILL, NULL, 0); + siginfo_t info; + memset(&info, 0, sizeof(info)); + waitid(P_PIDFD, pidfd, &info, 0); #endif + } + if(ret < 0){ + kill(pid, SIGKILL); + } // process ought be available immediately following waitid(), so supply // WNOHANG to avoid possible lockups due to weirdness if(pid != waitpid(pid, status, WNOHANG)){