FreeBSD regtest: add fakes for older versions in scalar
[valgrind.git] / memcheck / tests / freebsd / pdfork_pdkill.c
blobdb3e81bb4c1e641953d87940e3b1ae81d89cfe17
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.
8 //
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
13 // % ./pdfork
14 // usage: pdfork <child-sleep> <parent-wait>
15 // % ./pdfork 2 10
16 // child: exit
17 // parent: child exited
18 // % ./pdfork 10 2
19 // parent: kill
22 #include <sys/types.h>
23 #include <sys/select.h>
24 #include <sys/procdesc.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <errno.h>
30 #define DURATION_MAX 100
32 static long time_or_die(const char *str, const char *name) {
33 char *cptr;
34 long res;
36 res = strtol(str, &cptr, 10);
37 if (errno == ERANGE || *cptr != '\0') {
38 fprintf(stderr, "invalid %s parameter\n", name);
39 exit(EXIT_FAILURE);
40 } else if (res < 0 || res > DURATION_MAX) {
41 fprintf(stderr, "%s out of permitted range\n", name);
42 exit(EXIT_FAILURE);
45 return res;
48 int main(int argc, char *argv[]) {
49 struct timeval to={0,0};
50 long child_sleep, parent_wait;
51 int fd, ret;
52 fd_set fds;
54 if (argc != 3) {
55 fprintf(stderr, "usage: pdfork <child-sleep> <parent-wait>\n");
56 return EXIT_FAILURE;
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) {
62 perror("pdfork");
63 return EXIT_FAILURE;
64 } else if (ret == 0) {
65 sleep((unsigned int)child_sleep);
66 fprintf(stderr, "child: exit\n");
67 exit(0);
68 } else {
69 FD_ZERO(&fds);
70 FD_SET(fd, &fds);
71 to.tv_sec = parent_wait;
72 if ((ret = select(fd+1, &fds, NULL, NULL, &to)) == -1) {
73 perror("select");
74 return EXIT_FAILURE;
75 } else if (ret == 0) {
76 fprintf(stderr, "parent: kill fd %d\n", fd);
77 pid_t pid;
78 pdgetpid(fd, &pid);
79 pdkill(fd, 9);
80 } else {
81 fprintf(stderr, "parent: child exited\n");
85 // and generate a couple of errors for valgrind
86 int *badfd = malloc(sizeof(int));
87 free(badfd);
88 if (pdfork(badfd, 0) > 0)
90 fprintf(stderr, "parent after 1st bad pdfork\n");
91 int anotherfd;
92 int badflag;
93 pid_t* pbadpid = malloc(sizeof(pid_t));
94 free(pbadpid);
95 pdgetpid(anotherfd, pbadpid);
96 pdfork(&anotherfd, badflag);
99 return EXIT_SUCCESS;