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 * $FreeBSD$ 17 */ 18 19 static void 20 write_frame(int fd, char *buf, unsigned long buflen) 21 { 22 fd_set wfd; 23 int i; 24 25 while (buflen) { 26 FD_ZERO(&wfd); 27 FD_SET(fd, &wfd); 28 i = select(fd+1, NULL, &wfd, NULL, NULL); 29 if (i < 0) 30 err(1, "select failed"); 31 if (i != 1) { 32 errx(1, "select returned unexpected value %d\n", i); 33 exit(1); 34 } 35 i = write(fd, buf, buflen); 36 if (i < 0) { 37 if (errno != EAGAIN) 38 warn("write failed"); 39 exit(1); 40 } 41 buf += i; 42 buflen -= i; 43 } 44 } 45 46 int 47 main(void) 48 { 49 /* any value over PIPE_SIZE should do */ 50 char buf[BIG_PIPE_SIZE]; 51 int i, flags, fd[2]; 52 53 if (pipe(fd) < 0) 54 errx(1, "pipe failed"); 55 56 flags = fcntl(fd[1], F_GETFL); 57 if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) { 58 printf("fcntl failed: %s\n", strerror(errno)); 59 exit(1); 60 } 61 62 switch (fork()) { 63 case -1: 64 err(1, "fork failed: %s\n", strerror(errno)); 65 break; 66 case 0: 67 close(fd[1]); 68 for (;;) { 69 /* Any small size should do */ 70 i = read(fd[0], buf, 256); 71 if (i == 0) 72 break; 73 if (i < 0) 74 err(1, "read"); 75 } 76 exit(0); 77 default: 78 break; 79 } 80 81 close(fd[0]); 82 memset(buf, 0, sizeof buf); 83 for (i = 0; i < 1000; i++) 84 write_frame(fd[1], buf, sizeof buf); 85 86 printf("ok\n"); 87 exit(0); 88 } 89