5 #include <sys/socket.h>
12 /* work out what fcntl flag to use for non-blocking */
14 # define NONBLOCK_FLAG O_NONBLOCK
16 # define NONBLOCK_FLAG O_NDELAY
18 # define NONBLOCK_FLAG FNDELAY
21 static int fdpair_pipe(int fd[2])
26 static int fdpair_socketpair(int fd[2])
28 return socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
31 /****************************************************************************
32 Set a fd into nonblocking mode.
33 ****************************************************************************/
34 static int set_nonblocking(int fd)
38 if((val = fcntl(fd, F_GETFL, 0)) == -1)
40 if (!(val & NONBLOCK_FLAG)) {
42 fcntl(fd, F_SETFL, val);
47 /****************************************************************************
48 Set a fd into blocking mode.
49 ****************************************************************************/
50 static int set_blocking(int fd)
54 if((val = fcntl(fd, F_GETFL, 0)) == -1)
56 if (val & NONBLOCK_FLAG) {
57 val &= ~NONBLOCK_FLAG;
58 fcntl(fd, F_SETFL, val);
63 static int fdpair_tcp(int fd[2])
67 int socklen = sizeof(sock);
72 fd[0] = fd[1] = listener = -1;
74 memset(&sock, 0, sizeof(sock));
76 if ((listener = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
78 setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
80 if (listen(listener, 1) != 0) goto failed;
82 if (getsockname(listener, &sock, &socklen) != 0) goto failed;
84 if ((fd[1] = socket(PF_INET, SOCK_STREAM, 0)) == -1) goto failed;
86 setsockopt(fd[1],SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
88 set_nonblocking(fd[1]);
90 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) == -1) {
91 if (errno != EINPROGRESS) goto failed;
96 if ((fd[0] = accept(listener, &sock, &len)) == -1) goto failed;
98 setsockopt(fd[0],SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
101 if (connect_done == 0) {
102 if (connect(fd[1],(struct sockaddr *)&sock,sizeof(sock)) != 0) goto failed;
111 if (fd[0] != -1) close(fd[0]);
112 if (fd[1] != -1) close(fd[1]);
113 if (listener != -1) close(listener);
118 static void testfn(char *name, int (*fn)(int fd[2]))
122 char *fname = "sockbug.tmp";
127 signal(SIGCHLD, SIG_IGN);
134 if ((pid=fork()) == 0) {
135 /* we will put the data in a file as well as in the socketpair */
136 dfile = open(fname, O_WRONLY|O_CREAT|O_TRUNC);
144 set_nonblocking(fd[1]);
146 while (write(fd[1], &c, 1) == 1)
153 waitpid(pid, NULL, 0);
156 while (read(fd[0], &c, 1) == 1) count++;
159 printf("%s: count was %d. Should have been %d\n",
160 name, count, (int)st.st_size);
165 int main(int argc, char *argv[])
167 testfn("tcp", fdpair_tcp);
168 testfn("pipe", fdpair_pipe);
169 testfn("socketpair", fdpair_socketpair);