xref: /freebsd/tools/test/stress2/misc/pddupfd.sh (revision 9c6ed9a88d3afb8bc9aba7cf852cc36e03bcd34c)
1#!/bin/sh
2
3set -u
4prog=$(basename "$0" .sh)
5cat > /tmp/$prog.c <<EOF
6/* \$Id: pddupfd.c,v 1.6 2026/07/04 17:48:47 kostik Exp kostik $ */
7
8#include <sys/types.h>
9#include <sys/fcntl.h>
10#include <sys/mman.h>
11#include <sys/procdesc.h>
12#include <sys/resource.h>
13#include <sys/wait.h>
14#include <machine/atomic.h>
15#include <err.h>
16#include <signal.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20
21#define MY_SYS_pdopenpid	603
22#define MY_SYS_pddupfd		604
23
24static int
25my_pdopenpid(pid_t pid, int flags)
26{
27	return (syscall(MY_SYS_pdopenpid, pid, flags));
28}
29
30static int
31my_pddupfd(pid_t pid, int remote_fd, int flags)
32{
33	return (syscall(MY_SYS_pddupfd, pid, remote_fd, flags));
34}
35
36static void
37check(int fd, int child, int *comm)
38{
39	struct __wrusage wu;
40	struct __siginfo si;
41	int error, f, pp, rfd, status, workfd;
42	char cmd[128];
43
44	error = pdgetpid(fd, &pp);
45	if (error == -1)
46		err(1, "pgdetpid");
47	printf("child pid %d %d\n", child, pp);
48
49	while ((rfd = (int)atomic_load_int(comm)) == -1)
50		;
51	if (rfd == -2)
52		errx(1, "open in child failed");
53	workfd = my_pddupfd(fd, rfd, 0);
54	if (workfd == -1)
55		err(1, "pddupfd");
56
57	f = fcntl(workfd, F_GETFD);
58	if (f == -1)
59		err(1, "F_GETFD %d", workfd);
60	f &= ~FD_CLOEXEC;
61	error = fcntl(workfd, F_SETFD, f);
62	if (error == -1)
63		err(1, "F_SETFD %d", workfd);
64
65	snprintf(cmd, sizeof(cmd), "cat 0<&%d", workfd);
66	system(cmd);
67	close(workfd);
68
69	atomic_store_int(comm, -1);
70	
71	error = pdwait(fd, &status, WEXITED, &wu, &si);
72	if (error == -1)
73		err(1, "pdwait");
74	printf("exited pid %d status %#x si.si_status %#x si.si_code %#x\n",
75	    pp, status, si.si_status, si.si_code);
76}
77
78int
79main(void)
80{
81	int *comm;
82	pid_t child;
83	int fd, workfd;
84
85	comm = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED |
86	    MAP_ANONYMOUS, -1, 0);
87	if (comm == MAP_FAILED)
88		err(1, "mmap");
89	atomic_store_int(comm, -1);
90
91	child = fork();
92	if (child == -1)
93		err(1, "fork");
94	if (child == 0) {
95		workfd = open("/etc/passwd", O_RDONLY);
96		if (workfd == -1) {
97			atomic_store_int(comm, -2);
98			err(1, "open");
99		}
100		atomic_store_int(comm, workfd);
101		while ((int)atomic_load_int(comm) >= 0)
102			sleep(1);
103		_exit(0x123);
104	}
105
106	fd = my_pdopenpid(child, 0);
107	if (fd == -1)
108		err(1, "pdopenpid");
109
110	check(fd, child, comm);
111	close(fd);
112}
113EOF
114
115cc -o /tmp/$prog -Wall -Wextra -g -O0 /tmp/$prog.c || exit 1
116
117../testcases/swap/swap -t 2m -i 20 &
118sleep 2
119
120cd /tmp
121s=0
122start=`date +%s`
123while [ $((`date +%s`- start)) -lt 120 ]; do
124	./$prog > /dev/null ; s=$?
125done
126[ $s -eq 124 ] && s=0
127while pkill swap; do :; done
128wait
129cd -
130
131rm /tmp/$prog /tmp/$prog.c
132exit $s
133