1 // this example taken from
2 // https://gist.github.com/sebcat/a61b2ed859cee16c560e
4 // FreeBSD has pdfork which uses file descriptors instead of PIDs for
5 // managing processes. This allows for race-less process supervision and
6 // for using the traditional multiplexing calls (e.g., select). There's no
7 // need wait()ing for SIGCHLD, &c.
9 // This example forks a child that sleeps for a certain time while the
10 // parent is waiting for the child to exit, or for a timeout to be reached,
11 // whichever comes first. The time values (in seconds) are provided from argv
14 // usage: pdfork <child-sleep> <parent-wait>
17 // parent: child exited
22 #include <sys/types.h>
23 #include <sys/select.h>
24 #include <sys/procdesc.h>
30 #define DURATION_MAX 100
32 static long time_or_die(const char *str
, const char *name
) {
36 res
= strtol(str
, &cptr
, 10);
37 if (errno
== ERANGE
|| *cptr
!= '\0') {
38 fprintf(stderr
, "invalid %s parameter\n", name
);
40 } else if (res
< 0 || res
> DURATION_MAX
) {
41 fprintf(stderr
, "%s out of permitted range\n", name
);
48 int main(int argc
, char *argv
[]) {
49 struct timeval to
={0,0};
50 long child_sleep
, parent_wait
;
55 fprintf(stderr
, "usage: pdfork <child-sleep> <parent-wait>\n");
59 child_sleep
= time_or_die(argv
[1], "child-sleep");
60 parent_wait
= time_or_die(argv
[2], "parent-wait");
61 if ((ret
= pdfork(&fd
, 0)) == -1) {
64 } else if (ret
== 0) {
65 sleep((unsigned int)child_sleep
);
66 fprintf(stderr
, "child: exit\n");
71 to
.tv_sec
= parent_wait
;
72 if ((ret
= select(fd
+1, &fds
, NULL
, NULL
, &to
)) == -1) {
75 } else if (ret
== 0) {
76 fprintf(stderr
, "parent: kill fd %d\n", fd
);
81 fprintf(stderr
, "parent: child exited\n");
85 // and generate a couple of errors for valgrind
86 int *badfd
= malloc(sizeof(int));
88 if (pdfork(badfd
, 0) > 0)
90 fprintf(stderr
, "parent after 1st bad pdfork\n");
93 pid_t
* pbadpid
= malloc(sizeof(pid_t
));
95 pdgetpid(anotherfd
, pbadpid
);
96 pdfork(&anotherfd
, badflag
);