summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorpb <pb@FreeBSD.org>2003-07-31 12:40:56 +0000
committerpb <pb@FreeBSD.org>2003-07-31 12:40:56 +0000
commitee50ebe2699e0160daca4b63c4d46a7c82fb78e5 (patch)
treee0af319952ae08456298f6ce6760cf4c974936ce /tools
parent3001b66e9f60d9319440a96b653b9ad4a1801291 (diff)
downloadFreeBSD-src-ee50ebe2699e0160daca4b63c4d46a7c82fb78e5.zip
FreeBSD-src-ee50ebe2699e0160daca4b63c4d46a7c82fb78e5.tar.gz
Add a regression test for the big pipe bug.
Suggested by: silby
Diffstat (limited to 'tools')
-rw-r--r--tools/regression/README1
-rw-r--r--tools/regression/pipe/Makefile16
-rw-r--r--tools/regression/pipe/bigpipetest.c78
3 files changed, 95 insertions, 0 deletions
diff --git a/tools/regression/README b/tools/regression/README
index 40595ec..c7ecdab 100644
--- a/tools/regression/README
+++ b/tools/regression/README
@@ -22,6 +22,7 @@ geom Some tests and an out-of-kernel simulator for the GEOM code
ia64_unaligned Tests unaligned reads on the IA64
nfsmmap Some tests to exercise some tricky cases in NFS and mmap
p1003_1b Exercise 1003.1B scheduler
+pipe Pipe code regression test
fsx General filesystem exerciser
sysvmsg SysV IPC Message Queue Regression Utility
sysvsem SysV IPC Semaphore Regression Utility
diff --git a/tools/regression/pipe/Makefile b/tools/regression/pipe/Makefile
new file mode 100644
index 0000000..ff9f501
--- /dev/null
+++ b/tools/regression/pipe/Makefile
@@ -0,0 +1,16 @@
+#
+# $FreeBSD$
+#
+# "make" then "make regress".
+#
+PROG= bigpipetest
+NOMAN= yes
+
+regress:
+ @if ./bigpipetest; then \
+ echo "PASS"; \
+ else \
+ echo "FAIL"; \
+ fi
+
+.include <bsd.prog.mk>
diff --git a/tools/regression/pipe/bigpipetest.c b/tools/regression/pipe/bigpipetest.c
new file mode 100644
index 0000000..1eb3776
--- /dev/null
+++ b/tools/regression/pipe/bigpipetest.c
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/pipe.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * Test for the non-blocking big pipe bug (write(2) returning
+ * EAGAIN while select(2) returns the descriptor as ready for write).
+ *
+ * $FreeBSD$
+ */
+
+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) {
+ perror("select");
+ exit(1);
+ }
+ if (i != 1) {
+ fprintf(stderr, "select returned unexpected value %d\n", i);
+ exit(1);
+ }
+ i = write(fd, buf, buflen);
+ if (i < 0) {
+ if (errno != EAGAIN)
+ perror("write");
+ exit(1);
+ }
+ buf += i;
+ buflen -= i;
+ }
+}
+
+int main()
+{
+ char buf[BIG_PIPE_SIZE]; /* any value over PIPE_SIZE should do */
+ int i, flags, fd[2];
+
+ if (pipe(fd) < 0) { perror("pipe"); exit(1); }
+
+ flags = fcntl(fd[1], F_GETFL);
+ if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
+ perror("fcntl");
+ exit(1);
+ }
+
+ switch (fork()) {
+ case -1:
+ perror("fork");
+ exit(1);
+ case 0:
+ close(fd[1]);
+ for (;;) {
+ i = read(fd[0], buf, 256); /* any small size should do */
+ if (i == 0) break;
+ if (i < 0) { perror("read"); exit(1); }
+ }
+ 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);
+ exit(0);
+}
OpenPOWER on IntegriCloud