Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148428058
D54879.id170418.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D54879.id170418.diff
View Options
diff --git a/include/spawn.h b/include/spawn.h
--- a/include/spawn.h
+++ b/include/spawn.h
@@ -126,8 +126,12 @@
#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
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -476,7 +476,9 @@
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
--- 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 @@
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 @@
{
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 @@
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 @@
* 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 @@
*/
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 @@
}
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 @@
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 @@
(*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);
+}
diff --git a/lib/libsys/amd64/Makefile.sys b/lib/libsys/amd64/Makefile.sys
--- a/lib/libsys/amd64/Makefile.sys
+++ b/lib/libsys/amd64/Makefile.sys
@@ -4,6 +4,7 @@
amd64_set_fsbase.c \
amd64_set_gsbase.c \
amd64_set_tlsbase.c \
- rfork_thread.S
+ rfork_thread.S \
+ pdrfork_thread.S
MDASM= vfork.S cerror.S getcontext.S
diff --git a/lib/libsys/amd64/Symbol.sys.map b/lib/libsys/amd64/Symbol.sys.map
--- a/lib/libsys/amd64/Symbol.sys.map
+++ b/lib/libsys/amd64/Symbol.sys.map
@@ -17,6 +17,10 @@
amd64_set_tlsbase;
};
+FBSD_1.9 {
+ pdrfork_thread;
+};
+
FBSDprivate_1.0 {
_vfork;
};
diff --git a/lib/libsys/amd64/pdrfork_thread.S b/lib/libsys/amd64/pdrfork_thread.S
new file mode 100644
--- /dev/null
+++ b/lib/libsys/amd64/pdrfork_thread.S
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2000 Peter Wemm <peter@FreeBSD.org>
+ * Copyright 2003 Alan L. Cox <alc@cs.rice.edu>
+ * Copyright 2026 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by
+ * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
+ * the FreeBSD Foundation.
+ */
+
+#include <machine/asm.h>
+/*
+ * With thanks to John Dyson for the original version of this.
+ */
+
+#include <SYS.h>
+
+/*
+ * %rdi %esi %rdx %rcx %r8 %r9
+ * pdrfork_thread(fdp, pdflags, rfflags, stack_addr, start_fnc, start_arg);
+ *
+ * fdp Pointer for the resulting fd location
+ * pdflags Flags as to pdfork.
+ * rfflags: Flags as to rfork.
+ * stack_addr: Top of stack for thread.
+ * start_fnc: Address of thread function to call in child.
+ * start_arg: Argument to pass to the thread function in child.
+ */
+
+ENTRY(pdrfork_thread)
+ pushq %rbx
+ pushq %r12
+ pushq %r13
+ movq %r8, %rbx
+ movq %r9, %r12
+ movq %rcx, %r13
+
+ /*
+ * Prepare and execute the thread creation syscall
+ */
+ _SYSCALL(pdrfork)
+ jb 2f
+
+ /*
+ * Check to see if we are in the parent or child
+ */
+ cmpl $0, %edx
+ jnz 1f
+ popq %r13
+ popq %r12
+ popq %rbx
+ ret
+
+ /*
+ * If we are in the child (new thread), then
+ * set-up the call to the internal subroutine. If it
+ * returns, then call __exit.
+ */
+1:
+ movq %r13, %rsp
+ movq %r12, %rdi
+ call *%rbx
+ movl %eax, %edi
+
+ /*
+ * Exit system call
+ */
+ _SYSCALL(exit)
+
+ /*
+ * Branch here if the thread creation fails:
+ */
+2:
+ popq %r13
+ popq %r12
+ popq %rbx
+ jmp HIDENAME(cerror)
+END(pdrfork_thread)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libsys/i386/Makefile.sys b/lib/libsys/i386/Makefile.sys
--- a/lib/libsys/i386/Makefile.sys
+++ b/lib/libsys/i386/Makefile.sys
@@ -1,7 +1,7 @@
SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \
i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c \
i386_clr_watch.c i386_set_watch.c i386_vm86.c \
- rfork_thread.S
+ rfork_thread.S pdrfork_thread.S
MDASM= vfork.S cerror.S getcontext.S syscall.S
diff --git a/lib/libsys/i386/Symbol.sys.map b/lib/libsys/i386/Symbol.sys.map
--- a/lib/libsys/i386/Symbol.sys.map
+++ b/lib/libsys/i386/Symbol.sys.map
@@ -20,6 +20,10 @@
x86_pkru_unprotect_range;
};
+FBSD_1.9 {
+ pdrfork_thread;
+};
+
FBSDprivate_1.0 {
_vfork;
};
diff --git a/lib/libsys/i386/pdrfork_thread.S b/lib/libsys/i386/pdrfork_thread.S
new file mode 100644
--- /dev/null
+++ b/lib/libsys/i386/pdrfork_thread.S
@@ -0,0 +1,101 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2000 Peter Wemm <peter@FreeBSD.org>
+ * Copyright 2026 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by
+ * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
+ * the FreeBSD Foundation.
+ */
+
+#include <machine/asm.h>
+/*
+ * With thanks to John Dyson for the original version of this.
+ */
+
+#include <SYS.h>
+
+/*
+ * 8 12 16 20 24 28
+ * rfork_thread(fdp, pdflags rfflags, stack_addr, start_fnc, start_arg);
+ *
+ * fdp Pointer for the resulting fd location
+ * pdflags Flags as to pdfork.
+ * rfflags: Flags as to rfork.
+ * stack_addr: Top of stack for thread.
+ * start_fnc: Address of thread function to call in child.
+ * start_arg: Argument to pass to the thread function in child.
+ */
+
+ENTRY(pdrfork_thread)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %esi
+
+ /*
+ * Push thread info onto the new thread's stack
+ */
+ movl 20(%ebp), %esi # get stack addr
+
+ subl $4, %esi
+ movl 28(%ebp), %eax # get start argument
+ movl %eax, (%esi)
+
+ subl $4, %esi
+ movl 24(%ebp), %eax # get start thread address
+ movl %eax, (%esi)
+
+ /*
+ * Prepare and execute the thread creation syscall
+ */
+ pushl 16(%ebp)
+ pushl 12(%ebp)
+ pushl 8(%ebp)
+ pushl $0
+ _SYSCALL(pdrfork)
+ jb 2f
+
+ /*
+ * Check to see if we are in the parent or child
+ */
+ cmpl $0, %edx
+ jnz 1f
+ addl $16, %esp
+ popl %esi
+ movl %ebp, %esp
+ popl %ebp
+ ret
+ .p2align 2
+
+ /*
+ * If we are in the child (new thread), then
+ * set-up the call to the internal subroutine. If it
+ * returns, then call __exit.
+ */
+1:
+ movl %esi,%esp
+ popl %eax
+ call *%eax
+ addl $4, %esp
+
+ /*
+ * Exit system call
+ */
+ pushl %eax
+ pushl $0
+ _SYSCALL(exit)
+
+ /*
+ * Branch here if the thread creation fails:
+ */
+2:
+ addl $16, %esp
+ popl %esi
+ movl %ebp, %esp
+ popl %ebp
+ jmp HIDENAME(cerror)
+END(pdrfork_thread)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -130,6 +130,7 @@
int pdkill(int, int);
int pdgetpid(int, pid_t *);
int pdwait(int, int *, int, struct __wrusage *, struct __siginfo *);
+pid_t pdrfork_thread(int *, int, int, void *, int (*)(void *), void *);
__END_DECLS
#endif /* _KERNEL */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 18, 7:33 PM (12 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29922679
Default Alt Text
D54879.id170418.diff (9 KB)
Attached To
Mode
D54879: Add posix_spawnattr_{get,set}procdescp_np(3)
Attached
Detach File
Event Timeline
Log In to Comment