xref: /openbsd-src/regress/sys/kern/kqueue/kqueue-exec.c (revision 391a0cc7e0c8423428e25d58a35438f6c9a24bfd)
1 /*	$OpenBSD: kqueue-exec.c,v 1.1 2023/08/20 15:19:34 visa Exp $	*/
2 
3 /*
4  * Copyright (c) 2023 Visa Hankala
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/types.h>
20 #include <sys/event.h>
21 #include <sys/time.h>
22 #include <sys/wait.h>
23 #include <err.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 #include "main.h"
32 
33 static void	do_exec_child(void);
34 static void	do_exec_parent(const char *, int);
35 
36 int
do_exec(const char * argv0)37 do_exec(const char *argv0)
38 {
39 	do_exec_parent(argv0, 0);
40 	do_exec_parent(argv0, 1);
41 	return 0;
42 }
43 
44 static void
do_exec_parent(const char * argv0,int cloexec)45 do_exec_parent(const char *argv0, int cloexec)
46 {
47 	char *args[] = {
48 		(char *)argv0,
49 		"-e",
50 		NULL
51 	};
52 	char fdbuf[12];
53 	pid_t pid;
54 	int kq, status;
55 
56 	if (getenv("REGRESS_KQUEUE_FD") != NULL) {
57 		do_exec_child();
58 		_exit(0);
59 	}
60 
61 	pid = fork();
62 	if (pid == -1)
63 		err(1, "fork");
64 	if (pid == 0) {
65 		kq = kqueue1(cloexec ? O_CLOEXEC : 0);
66 		if (kq == -1)
67 			err(1, "kqueue1");
68 		snprintf(fdbuf, sizeof(fdbuf), "%d", kq);
69 		if (setenv("REGRESS_KQUEUE_FD", fdbuf, 1) == -1)
70 			err(1, "setenv");
71 		if (setenv("REGRESS_KQUEUE_CLOEXEC",
72 		    cloexec ? "1" : "0", 1) == -1)
73 			err(1, "setenv 2");
74 		execv(argv0, args);
75 		err(1, "execve");
76 	}
77 	if (waitpid(pid, &status, 0) == -1)
78 		err(1, "waitpid");
79 	if (status != 0)
80 		errx(1, "child failed");
81 }
82 
83 static void
do_exec_child(void)84 do_exec_child(void)
85 {
86 	char *arg;
87 	int cloexec, fd;
88 
89 	arg = getenv("REGRESS_KQUEUE_FD");
90 	if (arg == NULL)
91 		errx(1, "fd arg is missing");
92 	fd = atoi(arg);
93 
94 	arg = getenv("REGRESS_KQUEUE_CLOEXEC");
95 	if (arg != NULL && strcmp(arg, "1") == 0)
96 		cloexec = 1;
97 	else
98 		cloexec = 0;
99 
100 	if (cloexec) {
101 		if (kevent(fd, NULL, 0, NULL, 0, 0) == -1) {
102 			if (errno != EBADF)
103 				err(1, "child after exec: kevent cloexec");
104 		} else {
105 			errx(1, "child after exec: "
106 			    "kqueue cloexec fd is not closed");
107 		}
108 	} else {
109 		if (kevent(fd, NULL, 0, NULL, 0, 0) == -1) {
110 			err(1, "child after exec: kevent");
111 		}
112 	}
113 }
114