Re: Is anybody working on extending procdesc support to rfork?

Konstantin Belousov <[email protected]> Thu, 8 Jan 2026 09:14:59 +0200
Newsgroups gmane.os.freebsd.architechture
Message-ID <aV9Zc_K1u4956RIX__40947.0305357658$1767856540$gmane$org@kib.kiev.ua>
On Wed, Jan 07, 2026 at 08:42:59PM -0700, Alan Somers wrote:
> On Wed, Jan 7, 2026 at 8:02 PM Rob Norris <[email protected]> wrote:
> >
> > On Thu, 8 Jan 2026, at 1:40 PM, Konstantin Belousov wrote:
> >
> > That's fair.  The bug report references discussion at
> >  https://lists.cam.ac.uk/pipermail/cl-capsicum-discuss/2015-May/msg00012.html
> > which seems to be no longer available.  Does anybody have a pointer
> > to it?
> >
> >
> > Looks like a change to the mailing list archive software. I guess this or something in the same thread.
> >
> > https://lists.cam.ac.uk/sympa/arc/cl-capsicum-discuss/2015-05/msg00012.html
> >
> 
> Thanks for finding that!  There's two important pieces of information there:
> 
> * "we reserve the PID until all of its PDs had been closed".  If
> that's true, then it's possible to use wait4 with process descriptors
> race-free.  That would be good enough for my current purposes.  A
> proper  pdwait4() would still be useful for capability-mode processes,
> however.
> 
> * Ed Shouten already wrote a pdwait(3) on top of kqueue (though the
> link is dead).  I might be able to use that.
> 
> I'll investigate both of the above points tomorrow.

I added some version of pdwait(2) as well.

Mine does not reap the referenced child, it is the job of close().
More, this allows more than one process to pdwait() and get the expected
results.  I do not return pid from pdwait(), I see no point in mimicking
wait(2) there.

It worked for me with the following simple test program:

/* $Id: pdrfork.c,v 1.6 2026/01/08 07:00:36 kostik Exp kostik $ */

#include <sys/procdesc.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

#ifndef	SYS_pdrfork
#define	SYS_pdrfork	600

static int
pdrfork(int *fdp, int pdflags, int rfflags)
{
	return (syscall(SYS_pdrfork, fdp, pdflags, rfflags));
}

#endif
#ifndef	SYS_pdwait
#define	SYS_pdwait	601

static pid_t
pdwait(int fd, int options, int *status, struct __wrusage *wrp,
    siginfo_t *sip)
{
	return (syscall(SYS_pdwait, fd, options, status, wrp, sip));
}
#endif

int
main(void)
{
	struct __wrusage wr;
	siginfo_t si;
	int error, fd, pid, pid1, status;

	fd = -1;
	pid = pdrfork(&fd, 0, RFPROC | RFPROCDESC);
	if (pid == -1)
		err(1, "pdrfork");

	if (pid == 0) {
		sleep(1);
		_exit(12);
	}

	error = pdgetpid(fd, &pid1);
	if (error != 0)
		err(1, "pdgetpid");
	printf("fd %d pid %d getpid %d\n", fd, pid, pid1);
	status = -1;
	error = pdwait(fd, WEXITED, &status, &wr, &si);
	if (error != 0)
		err(1, "pdwait");
	printf("status %#x\n", status);
	close(fd);
	return (0);
}