summaryrefslogtreecommitdiffstats
path: root/tests/sys/kern/pipe/big_pipe_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/sys/kern/pipe/big_pipe_test.c')
-rw-r--r--tests/sys/kern/pipe/big_pipe_test.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/tests/sys/kern/pipe/big_pipe_test.c b/tests/sys/kern/pipe/big_pipe_test.c
new file mode 100644
index 0000000..fa5687e
--- /dev/null
+++ b/tests/sys/kern/pipe/big_pipe_test.c
@@ -0,0 +1,88 @@
+#include <sys/select.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BIG_PIPE_SIZE 64*1024 /* From sys/pipe.h */
+
+/*
+ * Test for the non-blocking big pipe bug (write(2) returning
+ * EAGAIN while select(2) returns the descriptor as ready for write).
+ *
+ * $FreeBSD$
+ */
+
+static void
+write_frame(int fd, char *buf, unsigned long buflen)
+{
+ fd_set wfd;
+ int i;
+
+ while (buflen) {
+ FD_ZERO(&wfd);
+ FD_SET(fd, &wfd);
+ i = select(fd+1, NULL, &wfd, NULL, NULL);
+ if (i < 0)
+ err(1, "select failed");
+ if (i != 1) {
+ errx(1, "select returned unexpected value %d\n", i);
+ exit(1);
+ }
+ i = write(fd, buf, buflen);
+ if (i < 0) {
+ if (errno != EAGAIN)
+ warn("write failed");
+ exit(1);
+ }
+ buf += i;
+ buflen -= i;
+ }
+}
+
+int
+main(void)
+{
+ /* any value over PIPE_SIZE should do */
+ char buf[BIG_PIPE_SIZE];
+ int i, flags, fd[2];
+
+ if (pipe(fd) < 0)
+ errx(1, "pipe failed");
+
+ flags = fcntl(fd[1], F_GETFL);
+ if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
+ printf("fcntl failed: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ switch (fork()) {
+ case -1:
+ err(1, "fork failed: %s\n", strerror(errno));
+ break;
+ case 0:
+ close(fd[1]);
+ for (;;) {
+ /* Any small size should do */
+ i = read(fd[0], buf, 256);
+ if (i == 0)
+ break;
+ if (i < 0)
+ err(1, "read");
+ }
+ exit(0);
+ default:
+ break;
+ }
+
+ close(fd[0]);
+ memset(buf, 0, sizeof buf);
+ for (i = 0; i < 1000; i++)
+ write_frame(fd[1], buf, sizeof buf);
+
+ printf("ok\n");
+ exit(0);
+}
OpenPOWER on IntegriCloud