The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=080d8ed7dd29ba537ce4cca286ed3369aca61ef5
commit 080d8ed7dd29ba537ce4cca286ed3369aca61ef5 Author: Konstantin Belousov <[email protected]> AuthorDate: 2026-01-25 17:40:48 +0000 Commit: Konstantin Belousov <[email protected]> CommitDate: 2026-01-26 19:30:14 +0000 libc: add posix_spawnattr_{get,set}procdescp_np Reviewed by: asomers Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54879 --- include/spawn.h | 4 ++++ lib/libc/gen/Symbol.map | 2 ++ lib/libc/gen/posix_spawn.c | 54 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/include/spawn.h b/include/spawn.h index a8f40e49dce0..636b20755238 100644 --- a/include/spawn.h +++ b/include/spawn.h @@ -126,8 +126,12 @@ int posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict, #if __BSD_VISIBLE int posix_spawnattr_setexecfd_np(posix_spawnattr_t * __restrict, int); +int posix_spawnattr_setprocdescp_np(const posix_spawnattr_t * __restrict, + int * __restrict, int); int posix_spawnattr_getexecfd_np(const posix_spawnattr_t * __restrict, int * __restrict); +int posix_spawnattr_getprocdescp_np(const posix_spawnattr_t * __restrict, + int ** __restrict, int * __restrict); #endif __END_DECLS diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 19170768ef7c..ddbd0522e13f 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -476,7 +476,9 @@ FBSD_1.8 { FBSD_1.9 { posix_spawnattr_getexecfd_np; + posix_spawnattr_getprocdescp_np; posix_spawnattr_setexecfd_np; + posix_spawnattr_setprocdescp_np; }; FBSDprivate_1.0 { diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c index fc327e15bbf0..c64915078317 100644 --- a/lib/libc/gen/posix_spawn.c +++ b/lib/libc/gen/posix_spawn.c @@ -29,6 +29,7 @@ #include "namespace.h" #include <sys/param.h> #include <sys/procctl.h> +#include <sys/procdesc.h> #include <sys/queue.h> #include <sys/wait.h> @@ -37,6 +38,7 @@ #include <sched.h> #include <spawn.h> #include <signal.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -51,6 +53,8 @@ struct __posix_spawnattr { sigset_t sa_sigdefault; sigset_t sa_sigmask; int sa_execfd; + int *sa_pdrfork_fdp; + int sa_pdflags; }; struct __posix_spawn_file_actions { @@ -281,6 +285,8 @@ do_posix_spawn(pid_t *pid, const char *path, { struct posix_spawn_args psa; pid_t p; + int pfd; + bool do_pfd; #ifdef _RFORK_THREAD_STACK_SIZE char *stack; size_t cnt, stacksz; @@ -322,6 +328,8 @@ do_posix_spawn(pid_t *pid, const char *path, psa.use_env_path = use_env_path; psa.error = 0; + do_pfd = sa != NULL && (*sa)->sa_pdrfork_fdp != NULL; + /* * Passing RFSPAWN to rfork(2) gives us effectively a vfork that drops * non-ignored signal handlers. We'll fall back to the slightly less @@ -341,10 +349,20 @@ do_posix_spawn(pid_t *pid, const char *path, * parent. Because of this, we must use rfork_thread instead while * almost every other arch stores the return address in a register. */ - p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa); + if (do_pfd) { + p = pdrfork_thread(&pfd, PD_CLOEXEC | (*sa)->sa_pdflags, + RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa); + } else { + p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, + &psa); + } free(stack); #else - p = rfork(RFSPAWN); + if (do_pfd) { + p = pdrfork(&pfd, PD_CLOEXEC | (*sa)->sa_pdflags, RFSPAWN); + } else { + p = rfork(RFSPAWN); + } if (p == 0) /* _posix_spawn_thr does not return */ _posix_spawn_thr(&psa); @@ -356,6 +374,8 @@ do_posix_spawn(pid_t *pid, const char *path, */ if (p == -1 && errno == EINVAL) { + if (do_pfd) + return (EOPNOTSUPP); p = vfork(); if (p == 0) /* _posix_spawn_thr does not return */ @@ -363,12 +383,18 @@ do_posix_spawn(pid_t *pid, const char *path, } if (p == -1) return (errno); - if (psa.error != 0) + if (psa.error != 0) { /* Failed; ready to reap */ - _waitpid(p, NULL, WNOHANG); - else if (pid != NULL) + if (do_pfd) + (void)_close(pfd); + else + _waitpid(p, NULL, WNOHANG); + } else if (pid != NULL) { /* exec succeeded */ *pid = p; + if (do_pfd) + *((*sa)->sa_pdrfork_fdp) = pfd; + } return (psa.error); } @@ -651,6 +677,15 @@ posix_spawnattr_getexecfd_np(const posix_spawnattr_t * __restrict sa, return (0); } +int +posix_spawnattr_getprocdescp_np(const posix_spawnattr_t * __restrict sa, + int ** __restrict fdpp, int * __restrict pdrflagsp) +{ + *fdpp = (*sa)->sa_pdrfork_fdp; + *pdrflagsp = (*sa)->sa_pdflags; + return (0); +} + int posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags) { @@ -708,3 +743,12 @@ posix_spawnattr_setexecfd_np(posix_spawnattr_t * __restrict sa, (*sa)->sa_execfd = execfd; return (0); } + +int +posix_spawnattr_setprocdescp_np(const posix_spawnattr_t * __restrict sa, + int * __restrict fdp, int pdrflags) +{ + (*sa)->sa_pdrfork_fdp = fdp; + (*sa)->sa_pdflags = pdrflags; + return (0); +}
