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 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 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