1 #include <sys/select.h>
2 #include <err.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <unistd.h>
9
10 #define BIG_PIPE_SIZE 64*1024 /* From sys/pipe.h */
11
12 /*
13 * Test for the non-blocking big pipe bug (write(2) returning
14 * EAGAIN while select(2) returns the descriptor as ready for write).
15 */
16
17 static void
write_frame(int fd,char * buf,unsigned long buflen)18 write_frame(int fd, char *buf, unsigned long buflen)
19 {
20 fd_set wfd;
21 int i;
22
23 while (buflen) {
24 FD_ZERO(&wfd);
25 FD_SET(fd, &wfd);
26 i = select(fd+1, NULL, &wfd, NULL, NULL);
27 if (i < 0)
28 err(1, "select failed");
29 if (i != 1) {
30 errx(1, "select returned unexpected value %d\n", i);
31 exit(1);
32 }
33 i = write(fd, buf, buflen);
34 if (i < 0) {
35 if (errno != EAGAIN)
36 warn("write failed");
37 exit(1);
38 }
39 buf += i;
40 buflen -= i;
41 }
42 }
43
44 int
main(void)45 main(void)
46 {
47 /* any value over PIPE_SIZE should do */
48 char buf[BIG_PIPE_SIZE];
49 int i, flags, fd[2];
50
51 if (pipe(fd) < 0)
52 errx(1, "pipe failed");
53
54 flags = fcntl(fd[1], F_GETFL);
55 if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
56 printf("fcntl failed: %s\n", strerror(errno));
57 exit(1);
58 }
59
60 switch (fork()) {
61 case -1:
62 err(1, "fork failed: %s\n", strerror(errno));
63 break;
64 case 0:
65 close(fd[1]);
66 for (;;) {
67 /* Any small size should do */
68 i = read(fd[0], buf, 256);
69 if (i == 0)
70 break;
71 if (i < 0)
72 err(1, "read");
73 }
74 exit(0);
75 default:
76 break;
77 }
78
79 close(fd[0]);
80 memset(buf, 0, sizeof buf);
81 for (i = 0; i < 1000; i++)
82 write_frame(fd[1], buf, sizeof buf);
83
84 printf("ok\n");
85 exit(0);
86 }
87