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