1290914Sngie#include <sys/select.h>
2290914Sngie#include <err.h>
3290914Sngie#include <errno.h>
4290914Sngie#include <fcntl.h>
5118262Spb#include <stdio.h>
6118262Spb#include <stdlib.h>
7118262Spb#include <string.h>
8290914Sngie#include <unistd.h>
9118262Spb
10132479Ssilby#define BIG_PIPE_SIZE  64*1024 /* From sys/pipe.h */
11132479Ssilby
12118262Spb/*
13118262Spb * Test for the non-blocking big pipe bug (write(2) returning
14118262Spb * EAGAIN while select(2) returns the descriptor as ready for write).
15118262Spb *
16118262Spb * $FreeBSD$
17118262Spb */
18118262Spb
19290914Sngiestatic void
20290914Sngiewrite_frame(int fd, char *buf, unsigned long buflen)
21118262Spb{
22290914Sngie	fd_set wfd;
23290914Sngie	int i;
24118262Spb
25290914Sngie	while (buflen) {
26290914Sngie		FD_ZERO(&wfd);
27290914Sngie		FD_SET(fd, &wfd);
28290914Sngie		i = select(fd+1, NULL, &wfd, NULL, NULL);
29290914Sngie		if (i < 0)
30290914Sngie			err(1, "select failed");
31290914Sngie		if (i != 1) {
32290914Sngie			errx(1, "select returned unexpected value %d\n", i);
33290914Sngie			exit(1);
34290914Sngie		}
35290914Sngie		i = write(fd, buf, buflen);
36290914Sngie		if (i < 0) {
37290914Sngie			if (errno != EAGAIN)
38290914Sngie				warn("write failed");
39290914Sngie			exit(1);
40290914Sngie		}
41290914Sngie		buf += i;
42290914Sngie		buflen -= i;
43118262Spb	}
44118262Spb}
45118262Spb
46290914Sngieint
47290914Sngiemain(void)
48118262Spb{
49290914Sngie	/* any value over PIPE_SIZE should do */
50290914Sngie	char buf[BIG_PIPE_SIZE];
51290914Sngie	int i, flags, fd[2];
52118262Spb
53290914Sngie	if (pipe(fd) < 0)
54290914Sngie		errx(1, "pipe failed");
55137587Snik
56290914Sngie	flags = fcntl(fd[1], F_GETFL);
57290914Sngie	if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
58290914Sngie		printf("fcntl failed: %s\n", strerror(errno));
59290914Sngie		exit(1);
60290914Sngie	}
61118262Spb
62290914Sngie	switch (fork()) {
63118262Spb	case -1:
64290914Sngie		err(1, "fork failed: %s\n", strerror(errno));
65290914Sngie		break;
66118262Spb	case 0:
67290914Sngie		close(fd[1]);
68290914Sngie		for (;;) {
69290914Sngie			/* Any small size should do */
70290914Sngie			i = read(fd[0], buf, 256);
71290914Sngie			if (i == 0)
72290914Sngie				break;
73290914Sngie			if (i < 0)
74290914Sngie				err(1, "read");
75290914Sngie		}
76290914Sngie		exit(0);
77118262Spb	default:
78290914Sngie		break;
79290914Sngie	}
80118262Spb
81290914Sngie	close(fd[0]);
82290914Sngie	memset(buf, 0, sizeof buf);
83290914Sngie	for (i = 0; i < 1000; i++)
84290914Sngie		write_frame(fd[1], buf, sizeof buf);
85290914Sngie
86290914Sngie	printf("ok\n");
87290914Sngie	exit(0);
88118262Spb}
89