git: f68ddd04ae06 - stable/15 - libc: add posix_spawnattr_{get,set}procdescp_np
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 01 Feb 2026 21:41:10 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=f68ddd04ae06f7a30a87e3cfb868442a46fba919
commit f68ddd04ae06f7a30a87e3cfb868442a46fba919
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-25 17:40:48 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-02-01 21:38:50 +0000
libc: add posix_spawnattr_{get,set}procdescp_np
(cherry picked from commit 080d8ed7dd29ba537ce4cca286ed3369aca61ef5)
---
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);
+}