xref: /freebsd/tools/test/stress2/misc/socketpair3.sh (revision 1d386b48)
1#!/bin/sh
2
3# Bug 227285 - File descriptor passing does not work reliably on SMP system
4# (cache coherency issue?)
5# "socketpair3: read failed in parent: 0, so_error: No error: 0 (0), ret2: 0"
6# seen.
7
8# Original test scenario by: jan.kokemueller@gmail.com
9
10# Page fault seen in WiP socket code.
11
12. ../default.cfg
13dir=/tmp
14odir=`pwd`
15cd $dir
16sed '1,/^EOF/d' < $odir/$0 > $dir/socketpair3.c
17mycc -o socketpair3 -Wall -Wextra -O0 -g socketpair3.c -lnv || exit 1
18rm -f socketpair3.c
19cd $odir
20
21for i in `jot 6`; do
22	$dir/socketpair3 &
23	pids="$pids $!"
24done
25s=0
26for i in $pids; do
27	wait $i
28	[ $? -ne 0 ] && s=1
29done
30[ -f socketpair3.core -a $s -eq 0 ] &&
31    { ls -l socketpair3.core; mv socketpair3.core /tmp; s=1; }
32
33rm -rf $dir/socketpair3
34exit $s
35
36EOF
37#include <sys/types.h>
38
39#include <sys/procdesc.h>
40#include <sys/socket.h>
41#include <sys/wait.h>
42
43#include <err.h>
44#include <poll.h>
45#include <signal.h>
46#include <stdio.h>
47#include <string.h>
48#include <time.h>
49#include <unistd.h>
50
51// From libnv.
52extern int fd_send(int sock, const int *fds, size_t nfds);
53extern int fd_recv(int sock, int *fds, size_t nfds);
54
55int main(void)
56{
57	pid_t pid;
58	time_t start;
59	int child_fd;
60	int sock[2];
61
62	start = time(NULL);
63	while (time(NULL) - start < 60) {
64		if (socketpair(PF_UNIX, SOCK_STREAM, 0, sock) < 0)
65			err(1, "socketpair");
66
67		pid = pdfork(&child_fd, PD_CLOEXEC);
68		if (pid < 0)
69			err(1, "pdfork");
70
71		if (pid == 0) {
72			ssize_t ret;
73			int sock_child[2];
74			int dummy = 0;
75
76			close(sock[0]);
77			if (socketpair(PF_UNIX, SOCK_STREAM, /**/
78			    0, sock_child) < 0)
79				err(1, "socketpair");
80
81			if (fd_send(sock[1], &sock_child[0], 1) != 0)
82				errx(1, "fd_send failed");
83#ifdef WORKAROUND
84			if (read(sock[1], &dummy, 1) != 1)
85				err(1, "write");
86#endif
87
88			close(sock_child[0]);
89
90			if (write(sock_child[1], &dummy, 1) != 1)
91				err(1, "write");
92
93			if ((ret = read(sock_child[1], &dummy, 1)) != 1)
94				errx(1, "read failed in child: %d",
95				    (int)ret);
96
97			close(sock_child[1]);
98
99			_exit(0);
100		}
101
102		close(sock[1]);
103
104		int sock_child;
105		uint8_t dummy;
106
107		if (fd_recv(sock[0], &sock_child, 1) != 0)
108			errx(1, "fd_recv failed");
109#ifdef WORKAROUND
110		if (write(sock[0], &dummy, 1) != 1)
111			err(1, "write");
112#endif
113
114		ssize_t ret;
115		if ((ret = read(sock_child, &dummy, 1)) != 1) {
116			int error;
117			socklen_t err_len = sizeof(error);
118
119			if (getsockopt(sock_child, SOL_SOCKET, SO_ERROR,
120			    &error, &err_len) < 0)
121				err(1, "getsockopt");
122
123			ssize_t ret2 = read(sock_child, &dummy, 1);
124
125			errx(1,
126			    "read failed in parent: %d, so_error: %s (%d), "
127			    "ret2: %d", (int)ret, strerror(error), error,
128			    (int)ret2);
129		}
130
131		if (write(sock_child, &dummy, 1) != 1)
132			err(1, "write");
133
134		close(sock_child);
135
136		struct pollfd pfd = { .fd = child_fd };
137		poll(&pfd, 1, -1);
138
139		close(child_fd);
140		close(sock[0]);
141	}
142
143	return (0);
144}
145