summaryrefslogtreecommitdiffstats
path: root/tools/regression
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-07-12 12:50:43 +0000
committerkib <kib@FreeBSD.org>2009-07-12 12:50:43 +0000
commitd144bd09876b8dea20687370a97bed68d1e1dd5e (patch)
tree1ee90370bde6284d60e817d235e4060d2ce313dd /tools/regression
parent871f788d7999e4e656af64c93e1382a8945f4399 (diff)
downloadFreeBSD-src-d144bd09876b8dea20687370a97bed68d1e1dd5e.zip
FreeBSD-src-d144bd09876b8dea20687370a97bed68d1e1dd5e.tar.gz
Test suite for the poll(2)/select(2) on fifos, pipes and sockets,
and recorded results for several operating systems. Submitted by: bde Approved by: re (kensmith)
Diffstat (limited to 'tools/regression')
-rw-r--r--tools/regression/poll/4/pipepoll.out21
-rw-r--r--tools/regression/poll/4/pipeselect.out21
-rw-r--r--tools/regression/poll/7/pipepoll.out21
-rw-r--r--tools/regression/poll/7/pipeselect.out21
-rw-r--r--tools/regression/poll/Makefile35
-rw-r--r--tools/regression/poll/Readme18
-rw-r--r--tools/regression/poll/l/pipepoll.out21
-rw-r--r--tools/regression/poll/l/pipeselect.out21
-rw-r--r--tools/regression/poll/m/pipepoll.out21
-rw-r--r--tools/regression/poll/m/pipeselect.out21
-rw-r--r--tools/regression/poll/n/pipepoll.out21
-rw-r--r--tools/regression/poll/n/pipeselect.out21
-rw-r--r--tools/regression/poll/pipepoll.c302
-rw-r--r--tools/regression/poll/pipeselect.c318
14 files changed, 883 insertions, 0 deletions
diff --git a/tools/regression/poll/4/pipepoll.out b/tools/regression/poll/4/pipepoll.out
new file mode 100644
index 0000000..0a42491
--- /dev/null
+++ b/tools/regression/poll/4/pipepoll.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected 0; got 0
+ok 2 Pipe state 5: expected POLLIN; got POLLIN
+ok 3 Pipe state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+not ok 4 Pipe state 6a: expected POLLHUP; got POLLIN | POLLHUP
+ok 5 Sock state 4: expected 0; got 0
+ok 6 Sock state 5: expected POLLIN; got POLLIN
+not ok 7 Sock state 6: expected POLLIN | POLLHUP; got POLLIN
+not ok 8 Sock state 6a: expected POLLHUP; got POLLIN
+not ok 9 FIFO state 0: expected 0; got POLLIN
+ok 10 FIFO state 1: expected 0; got 0
+ok 11 FIFO state 2: expected POLLIN; got POLLIN
+ok 12 FIFO state 2a: expected 0; got 0
+not ok 13 FIFO state 3: expected POLLHUP; got POLLIN
+ok 14 FIFO state 4: expected 0; got 0
+ok 15 FIFO state 5: expected POLLIN; got POLLIN
+not ok 16 FIFO state 6: expected POLLIN | POLLHUP; got POLLIN
+not ok 17 FIFO state 6a: expected POLLHUP; got POLLIN
+not ok 18 FIFO state 6b: expected 0; got POLLIN
+not ok 19 FIFO state 6c: expected POLLHUP; got POLLIN
+not ok 20 FIFO state 6d: expected POLLHUP; got POLLIN
diff --git a/tools/regression/poll/4/pipeselect.out b/tools/regression/poll/4/pipeselect.out
new file mode 100644
index 0000000..3eaca3a
--- /dev/null
+++ b/tools/regression/poll/4/pipeselect.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected clear; got clear
+ok 2 Pipe state 5: expected set; got set
+ok 3 Pipe state 6: expected set; got set
+ok 4 Pipe state 6a: expected set; got set
+ok 5 Sock state 4: expected clear; got clear
+ok 6 Sock state 5: expected set; got set
+ok 7 Sock state 6: expected set; got set
+ok 8 Sock state 6a: expected set; got set
+not ok 9 FIFO state 0: expected clear; got set
+ok 10 FIFO state 1: expected clear; got clear
+ok 11 FIFO state 2: expected set; got set
+ok 12 FIFO state 2a: expected clear; got clear
+ok 13 FIFO state 3: expected set; got set
+ok 14 FIFO state 4: expected clear; got clear
+ok 15 FIFO state 5: expected set; got set
+ok 16 FIFO state 6: expected set; got set
+ok 17 FIFO state 6a: expected set; got set
+not ok 18 FIFO state 6b: expected clear; got set
+ok 19 FIFO state 6c: expected set; got set
+ok 20 FIFO state 6d: expected set; got set
diff --git a/tools/regression/poll/7/pipepoll.out b/tools/regression/poll/7/pipepoll.out
new file mode 100644
index 0000000..3794735
--- /dev/null
+++ b/tools/regression/poll/7/pipepoll.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected 0; got 0
+ok 2 Pipe state 5: expected POLLIN; got POLLIN
+ok 3 Pipe state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+not ok 4 Pipe state 6a: expected POLLHUP; got POLLIN | POLLHUP
+ok 5 Sock state 4: expected 0; got 0
+ok 6 Sock state 5: expected POLLIN; got POLLIN
+not ok 7 Sock state 6: expected POLLIN | POLLHUP; got POLLIN
+not ok 8 Sock state 6a: expected POLLHUP; got POLLIN
+ok 9 FIFO state 0: expected 0; got 0
+ok 10 FIFO state 1: expected 0; got 0
+ok 11 FIFO state 2: expected POLLIN; got POLLIN
+ok 12 FIFO state 2a: expected 0; got 0
+not ok 13 FIFO state 3: expected POLLHUP; got 0
+ok 14 FIFO state 4: expected 0; got 0
+ok 15 FIFO state 5: expected POLLIN; got POLLIN
+not ok 16 FIFO state 6: expected POLLIN | POLLHUP; got POLLIN
+not ok 17 FIFO state 6a: expected POLLHUP; got 0
+ok 18 FIFO state 6b: expected 0; got 0
+not ok 19 FIFO state 6c: expected POLLHUP; got 0
+not ok 20 FIFO state 6d: expected POLLHUP; got 0
diff --git a/tools/regression/poll/7/pipeselect.out b/tools/regression/poll/7/pipeselect.out
new file mode 100644
index 0000000..5e64a27
--- /dev/null
+++ b/tools/regression/poll/7/pipeselect.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected clear; got clear
+ok 2 Pipe state 5: expected set; got set
+ok 3 Pipe state 6: expected set; got set
+ok 4 Pipe state 6a: expected set; got set
+ok 5 Sock state 4: expected clear; got clear
+ok 6 Sock state 5: expected set; got set
+ok 7 Sock state 6: expected set; got set
+ok 8 Sock state 6a: expected set; got set
+ok 9 FIFO state 0: expected clear; got clear
+ok 10 FIFO state 1: expected clear; got clear
+ok 11 FIFO state 2: expected set; got set
+ok 12 FIFO state 2a: expected clear; got clear
+not ok 13 FIFO state 3: expected set; got clear
+ok 14 FIFO state 4: expected clear; got clear
+ok 15 FIFO state 5: expected set; got set
+ok 16 FIFO state 6: expected set; got set
+not ok 17 FIFO state 6a: expected set; got clear
+ok 18 FIFO state 6b: expected clear; got clear
+not ok 19 FIFO state 6c: expected set; got clear
+not ok 20 FIFO state 6d: expected set; got clear
diff --git a/tools/regression/poll/Makefile b/tools/regression/poll/Makefile
new file mode 100644
index 0000000..ac3ff90
--- /dev/null
+++ b/tools/regression/poll/Makefile
@@ -0,0 +1,35 @@
+$ $FreeBSD$
+# This makefile has been uglified for portability.
+# Nothing yet works with gmake for the path to the sources.
+.PATH: ..
+
+PROG= pipepoll pipeselect
+CFLAGS+= -Werror -Wall
+
+all: ${PROG}
+pipepoll: pipepoll.c
+pipeselect: pipeselect.c
+
+pipepoll pipeselect:
+ ${CC} ${CFLAGS} ${LDFLAGS} -o $@ $@.c
+
+test: all
+ -for prog in ${PROG}; do \
+ ./$${prog} > $${prog}.out.new; \
+ diff -u1 $${prog}.out $${prog}.out.new; \
+ done
+
+clean:
+ for prog in ${PROG}; do \
+ rm -f $${prog} $${prog}.out.new; \
+ done
+
+rename:
+ for prog in ${PROG}; do \
+ mv $${prog}.out.new $${prog}.out; \
+ done
+
+veryclean: clean
+ for prog in ${PROG}; do \
+ rm -f $${prog}.out; \
+ done
diff --git a/tools/regression/poll/Readme b/tools/regression/poll/Readme
new file mode 100644
index 0000000..6583794
--- /dev/null
+++ b/tools/regression/poll/Readme
@@ -0,0 +1,18 @@
+$FreeBSD$
+
+The directory contains poll(2) and select(2) compliance (and more) tests
+from Bruce Evans, together with canned test results from several systems
+for reference.
+
+Citing Bruce Evans:
+The subdirectories contain results of old runs:
+
+{4,7}: FreeBSD-{4,7} with old tests (only state 0 and 6b have different
+expectations; state 0 fails in FreeBSD-4 so the above is wrong
+about at least when it was broken. I thought that I fixed it
+completely for select() in FreeBSD-1. One or both of these states
+were very broken in Net/2 and maybe in 4.4BSD-Lite*).
+
+l: Linux-2.6.10 with old tests (only state 0 has different expectations)
+m: my current version of FreeBSD with old tests (0 and 6b)
+n: my previous version of FreeBSD with old tests (0 and 6b)
diff --git a/tools/regression/poll/l/pipepoll.out b/tools/regression/poll/l/pipepoll.out
new file mode 100644
index 0000000..b8f2136
--- /dev/null
+++ b/tools/regression/poll/l/pipepoll.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected 0; got 0
+ok 2 Pipe state 5: expected POLLIN; got POLLIN
+ok 3 Pipe state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 4 Pipe state 6a: expected POLLHUP; got POLLHUP
+ok 5 Sock state 4: expected 0; got 0
+ok 6 Sock state 5: expected POLLIN; got POLLIN
+ok 7 Sock state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+not ok 8 Sock state 6a: expected POLLHUP; got POLLIN | POLLHUP
+ok 9 FIFO state 0: expected 0; got 0
+ok 10 FIFO state 1: expected 0; got 0
+ok 11 FIFO state 2: expected POLLIN; got POLLIN
+ok 12 FIFO state 2a: expected 0; got 0
+ok 13 FIFO state 3: expected POLLHUP; got POLLHUP
+ok 14 FIFO state 4: expected 0; got 0
+ok 15 FIFO state 5: expected POLLIN; got POLLIN
+ok 16 FIFO state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 17 FIFO state 6a: expected POLLHUP; got POLLHUP
+not ok 18 FIFO state 6b: expected POLLHUP; got 0
+ok 19 FIFO state 6c: expected POLLHUP; got POLLHUP
+ok 20 FIFO state 6d: expected POLLHUP; got POLLHUP
diff --git a/tools/regression/poll/l/pipeselect.out b/tools/regression/poll/l/pipeselect.out
new file mode 100644
index 0000000..452d7e1
--- /dev/null
+++ b/tools/regression/poll/l/pipeselect.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected clear; got clear
+ok 2 Pipe state 5: expected set; got set
+ok 3 Pipe state 6: expected set; got set
+ok 4 Pipe state 6a: expected set; got set
+ok 5 Sock state 4: expected clear; got clear
+ok 6 Sock state 5: expected set; got set
+ok 7 Sock state 6: expected set; got set
+ok 8 Sock state 6a: expected set; got set
+not ok 9 FIFO state 0: expected set; got clear
+ok 10 FIFO state 1: expected clear; got clear
+ok 11 FIFO state 2: expected set; got set
+ok 12 FIFO state 2a: expected clear; got clear
+ok 13 FIFO state 3: expected set; got set
+ok 14 FIFO state 4: expected clear; got clear
+ok 15 FIFO state 5: expected set; got set
+ok 16 FIFO state 6: expected set; got set
+ok 17 FIFO state 6a: expected set; got set
+not ok 18 FIFO state 6b: expected set; got clear
+ok 19 FIFO state 6c: expected set; got set
+ok 20 FIFO state 6d: expected set; got set
diff --git a/tools/regression/poll/m/pipepoll.out b/tools/regression/poll/m/pipepoll.out
new file mode 100644
index 0000000..99c11fa
--- /dev/null
+++ b/tools/regression/poll/m/pipepoll.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected 0; got 0
+ok 2 Pipe state 5: expected POLLIN; got POLLIN
+ok 3 Pipe state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 4 Pipe state 6a: expected POLLHUP; got POLLHUP
+ok 5 Sock state 4: expected 0; got 0
+ok 6 Sock state 5: expected POLLIN; got POLLIN
+ok 7 Sock state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 8 Sock state 6a: expected POLLHUP; got POLLHUP
+ok 9 FIFO state 0: expected 0; got 0
+ok 10 FIFO state 1: expected 0; got 0
+ok 11 FIFO state 2: expected POLLIN; got POLLIN
+ok 12 FIFO state 2a: expected 0; got 0
+ok 13 FIFO state 3: expected POLLHUP; got POLLHUP
+ok 14 FIFO state 4: expected 0; got 0
+ok 15 FIFO state 5: expected POLLIN; got POLLIN
+ok 16 FIFO state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 17 FIFO state 6a: expected POLLHUP; got POLLHUP
+ok 18 FIFO state 6b: expected POLLHUP; got POLLHUP
+ok 19 FIFO state 6c: expected POLLHUP; got POLLHUP
+ok 20 FIFO state 6d: expected POLLHUP; got POLLHUP
diff --git a/tools/regression/poll/m/pipeselect.out b/tools/regression/poll/m/pipeselect.out
new file mode 100644
index 0000000..3cc37b4
--- /dev/null
+++ b/tools/regression/poll/m/pipeselect.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected clear; got clear
+ok 2 Pipe state 5: expected set; got set
+ok 3 Pipe state 6: expected set; got set
+ok 4 Pipe state 6a: expected set; got set
+ok 5 Sock state 4: expected clear; got clear
+ok 6 Sock state 5: expected set; got set
+ok 7 Sock state 6: expected set; got set
+ok 8 Sock state 6a: expected set; got set
+not ok 9 FIFO state 0: expected set; got clear
+ok 10 FIFO state 1: expected clear; got clear
+ok 11 FIFO state 2: expected set; got set
+ok 12 FIFO state 2a: expected clear; got clear
+ok 13 FIFO state 3: expected set; got set
+ok 14 FIFO state 4: expected clear; got clear
+ok 15 FIFO state 5: expected set; got set
+ok 16 FIFO state 6: expected set; got set
+ok 17 FIFO state 6a: expected set; got set
+ok 18 FIFO state 6b: expected set; got set
+ok 19 FIFO state 6c: expected set; got set
+ok 20 FIFO state 6d: expected set; got set
diff --git a/tools/regression/poll/n/pipepoll.out b/tools/regression/poll/n/pipepoll.out
new file mode 100644
index 0000000..83e4649
--- /dev/null
+++ b/tools/regression/poll/n/pipepoll.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected 0; got 0
+ok 2 Pipe state 5: expected POLLIN; got POLLIN
+ok 3 Pipe state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 4 Pipe state 6a: expected POLLHUP; got POLLHUP
+ok 5 Sock state 4: expected 0; got 0
+ok 6 Sock state 5: expected POLLIN; got POLLIN
+ok 7 Sock state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 8 Sock state 6a: expected POLLHUP; got POLLHUP
+ok 9 FIFO state 0: expected 0; got 0
+ok 10 FIFO state 1: expected 0; got 0
+ok 11 FIFO state 2: expected POLLIN; got POLLIN
+ok 12 FIFO state 2a: expected 0; got 0
+ok 13 FIFO state 3: expected POLLHUP; got POLLHUP
+ok 14 FIFO state 4: expected 0; got 0
+ok 15 FIFO state 5: expected POLLIN; got POLLIN
+ok 16 FIFO state 6: expected POLLIN | POLLHUP; got POLLIN | POLLHUP
+ok 17 FIFO state 6a: expected POLLHUP; got POLLHUP
+ok 18 FIFO state 6b: expected 0; got 0
+ok 19 FIFO state 6c: expected POLLHUP; got POLLHUP
+ok 20 FIFO state 6d: expected POLLHUP; got POLLHUP
diff --git a/tools/regression/poll/n/pipeselect.out b/tools/regression/poll/n/pipeselect.out
new file mode 100644
index 0000000..6256a49
--- /dev/null
+++ b/tools/regression/poll/n/pipeselect.out
@@ -0,0 +1,21 @@
+1..20
+ok 1 Pipe state 4: expected clear; got clear
+ok 2 Pipe state 5: expected set; got set
+ok 3 Pipe state 6: expected set; got set
+ok 4 Pipe state 6a: expected set; got set
+ok 5 Sock state 4: expected clear; got clear
+ok 6 Sock state 5: expected set; got set
+ok 7 Sock state 6: expected set; got set
+ok 8 Sock state 6a: expected set; got set
+ok 9 FIFO state 0: expected clear; got clear
+ok 10 FIFO state 1: expected clear; got clear
+ok 11 FIFO state 2: expected set; got set
+ok 12 FIFO state 2a: expected clear; got clear
+ok 13 FIFO state 3: expected set; got set
+ok 14 FIFO state 4: expected clear; got clear
+ok 15 FIFO state 5: expected set; got set
+ok 16 FIFO state 6: expected set; got set
+ok 17 FIFO state 6a: expected set; got set
+ok 18 FIFO state 6b: expected clear; got clear
+ok 19 FIFO state 6c: expected set; got set
+ok 20 FIFO state 6d: expected set; got set
diff --git a/tools/regression/poll/pipepoll.c b/tools/regression/poll/pipepoll.c
new file mode 100644
index 0000000..1cdcbea
--- /dev/null
+++ b/tools/regression/poll/pipepoll.c
@@ -0,0 +1,302 @@
+/* $FreeBSD$ */
+
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define FIFONAME "fifo.tmp"
+#define FT_END 3
+#define FT_FIFO 2
+#define FT_PIPE 0
+#define FT_SOCKETPAIR 1
+
+static int filetype;
+
+static const char *
+decode_events(int events)
+{
+ char *ncresult;
+ const char *result;
+
+ switch (events) {
+ case POLLIN:
+ result = "POLLIN";
+ break;
+ case POLLHUP:
+ result = "POLLHUP";
+ break;
+ case POLLIN | POLLHUP:
+ result = "POLLIN | POLLHUP";
+ break;
+ default:
+ asprintf(&ncresult, "%#x", events);
+ result = ncresult;
+ break;
+ }
+ return (result);
+}
+
+static void
+report(int num, const char *state, int expected, int got)
+{
+ if (expected == got)
+ printf("ok %-2d ", num);
+ else
+ printf("not ok %-2d", num);
+ printf(" %s state %s: expected %s; got %s\n",
+ filetype == FT_PIPE ? "Pipe" :
+ filetype == FT_SOCKETPAIR ? "Sock" : "FIFO",
+ state, decode_events(expected), decode_events(got));
+ fflush(stdout);
+}
+
+static pid_t cpid;
+static pid_t ppid;
+static volatile sig_atomic_t state;
+
+static void
+catch(int sig)
+{
+ state++;
+}
+
+static void
+child(int fd, int num)
+{
+ struct pollfd pfd;
+ int fd2;
+ char buf[256];
+
+ if (filetype == FT_FIFO) {
+ fd = open(FIFONAME, O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ err(1, "open for read");
+ }
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ if (filetype == FT_FIFO) {
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "0", 0, pfd.revents);
+ }
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 1)
+ ;
+ if (filetype != FT_FIFO) {
+ /*
+ * The connection cannot be reestablished. Use the code that
+ * delays the read until after the writer disconnects since
+ * that case is more interesting.
+ */
+ state = 4;
+ goto state4;
+ }
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "1", 0, pfd.revents);
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 2)
+ ;
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "2", POLLIN, pfd.revents);
+ if (read(fd, buf, sizeof buf) != 1)
+ err(1, "read");
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "2a", 0, pfd.revents);
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 3)
+ ;
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "3", POLLHUP, pfd.revents);
+ kill(ppid, SIGUSR1);
+
+ /*
+ * Now we expect a new writer, and a new connection too since
+ * we read all the data. The only new point is that we didn't
+ * start quite from scratch since the read fd is not new. Check
+ * startup state as above, but don't do the read as above.
+ */
+ usleep(1);
+ while (state != 4)
+ ;
+state4:
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "4", 0, pfd.revents);
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 5)
+ ;
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "5", POLLIN, pfd.revents);
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 6)
+ ;
+ /*
+ * Now we have no writer, but should still have data from the old
+ * writer. Check that we have both a data-readable condition and a
+ * hangup condition, and that the data can be read in the usual way.
+ * Since Linux does this, programs must not quit reading when they
+ * see POLLHUP; they must see POLLHUP without POLLIN (or another
+ * input condition) before they decide that there is EOF. gdb-6.1.1
+ * is an example of a broken program that quits on POLLHUP only --
+ * see its event-loop.c.
+ */
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "6", POLLIN | POLLHUP, pfd.revents);
+ if (read(fd, buf, sizeof buf) != 1)
+ err(1, "read");
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "6a", POLLHUP, pfd.revents);
+ if (filetype == FT_FIFO) {
+ /*
+ * Check that POLLHUP is sticky for a new reader and for
+ * the old reader.
+ */
+ fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK);
+ if (fd2 < 0)
+ err(1, "open for read");
+ pfd.fd = fd2;
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "6b", POLLHUP, pfd.revents);
+ pfd.fd = fd;
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "6c", POLLHUP, pfd.revents);
+ close(fd2);
+ if (poll(&pfd, 1, 0) < 0)
+ err(1, "poll");
+ report(num++, "6d", POLLHUP, pfd.revents);
+ }
+ close(fd);
+ kill(ppid, SIGUSR1);
+
+ exit(0);
+}
+
+static void
+parent(int fd)
+{
+ usleep(1);
+ while (state != 1)
+ ;
+ if (filetype == FT_FIFO) {
+ fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
+ if (fd < 0)
+ err(1, "open for write");
+ }
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 2)
+ ;
+ if (write(fd, "", 1) != 1)
+ err(1, "write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 3)
+ ;
+ if (close(fd) != 0)
+ err(1, "close for write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 4)
+ ;
+ if (filetype != FT_FIFO)
+ return;
+ fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
+ if (fd < 0)
+ err(1, "open for write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 5)
+ ;
+ if (write(fd, "", 1) != 1)
+ err(1, "write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 6)
+ ;
+ if (close(fd) != 0)
+ err(1, "close for write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 7)
+ ;
+}
+
+int
+main(void)
+{
+ int fd[2], num;
+
+ num = 1;
+ printf("1..20\n");
+ fflush(stdout);
+ signal(SIGUSR1, catch);
+ ppid = getpid();
+ for (filetype = 0; filetype < FT_END; filetype++) {
+ switch (filetype) {
+ case FT_FIFO:
+ if (mkfifo(FIFONAME, 0666) != 0)
+ err(1, "mkfifo");
+ fd[0] = -1;
+ fd[1] = -1;
+ break;
+ case FT_SOCKETPAIR:
+ if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC,
+ fd) != 0)
+ err(1, "socketpair");
+ break;
+ case FT_PIPE:
+ if (pipe(fd) != 0)
+ err(1, "pipe");
+ break;
+ }
+ state = 0;
+ switch (cpid = fork()) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ (void)close(fd[1]);
+ child(fd[0], num);
+ break;
+ default:
+ (void)close(fd[0]);
+ parent(fd[1]);
+ break;
+ }
+ num += filetype == FT_FIFO ? 12 : 4;
+ }
+ (void)unlink(FIFONAME);
+ return (0);
+}
diff --git a/tools/regression/poll/pipeselect.c b/tools/regression/poll/pipeselect.c
new file mode 100644
index 0000000..fe6e8ed
--- /dev/null
+++ b/tools/regression/poll/pipeselect.c
@@ -0,0 +1,318 @@
+/* $FreeBSD$ */
+
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define FIFONAME "fifo.tmp"
+#define FT_END 3
+#define FT_FIFO 2
+#define FT_PIPE 0
+#define FT_SOCKETPAIR 1
+
+#define SETUP(fd, rfds, tv) do { \
+ FD_ZERO(&(rfds)); \
+ FD_SET((fd), &(rfds)); \
+ (tv).tv_sec = 0; \
+ (tv).tv_usec = 0; \
+} while (0)
+
+static int filetype;
+
+static const char *
+decode_events(int events)
+{
+ return (events ? "set" : "clear");
+}
+
+static void
+report(int num, const char *state, int expected, int got)
+{
+ if (!expected == !got)
+ printf("ok %-2d ", num);
+ else
+ printf("not ok %-2d", num);
+ printf(" %s state %s: expected %s; got %s\n",
+ filetype == FT_PIPE ? "Pipe" :
+ filetype == FT_SOCKETPAIR ? "Sock" : "FIFO",
+ state, decode_events(expected), decode_events(got));
+ fflush(stdout);
+}
+
+static pid_t cpid;
+static pid_t ppid;
+static volatile sig_atomic_t state;
+
+static void
+catch(int sig)
+{
+ state++;
+}
+
+static void
+child(int fd, int num)
+{
+ fd_set rfds;
+ struct timeval tv;
+ int fd1, fd2;
+ char buf[256];
+
+ if (filetype == FT_FIFO) {
+ fd = open(FIFONAME, O_RDONLY | O_NONBLOCK);
+ if (fd < 0)
+ err(1, "open for read");
+ }
+ if (fd >= FD_SETSIZE)
+ errx(1, "fd = %d too large for select()", fd);
+
+ if (filetype == FT_FIFO) {
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ /*
+ * This state (a reader for which there has never been a
+ * writer) is reported quite differently for select() than
+ * for poll(). select() must see a ready-to-read descriptor
+ * since read() will see EOF and not block; it cannot
+ * distinguish this state from the one of a reader for which
+ * there has been a writer but all writers have gone away
+ * and all data has been read. poll() and distinguish these
+ * states by returning POLLHUP only for the latter; it does
+ * this, although this makes it inconsistent with the
+ * blockability of read() in the former.
+ */
+ report(num++, "0", 1, FD_ISSET(fd, &rfds));
+ }
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 1)
+ ;
+ if (filetype != FT_FIFO) {
+ /*
+ * The connection cannot be reestablished. Use the code that
+ * delays the read until after the writer disconnects since
+ * that case is more interesting.
+ */
+ state = 4;
+ goto state4;
+ }
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "1", 0, FD_ISSET(fd, &rfds));
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 2)
+ ;
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "2", 1, FD_ISSET(fd, &rfds));
+ if (read(fd, buf, sizeof buf) != 1)
+ err(1, "read");
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "2a", 0, FD_ISSET(fd, &rfds));
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 3)
+ ;
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "3", 1, FD_ISSET(fd, &rfds));
+ kill(ppid, SIGUSR1);
+
+ /*
+ * Now we expect a new writer, and a new connection too since
+ * we read all the data. The only new point is that we didn't
+ * start quite from scratch since the read fd is not new. Check
+ * startup state as above, but don't do the read as above.
+ */
+ usleep(1);
+ while (state != 4)
+ ;
+state4:
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "4", 0, FD_ISSET(fd, &rfds));
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 5)
+ ;
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "5", 1, FD_ISSET(fd, &rfds));
+ kill(ppid, SIGUSR1);
+
+ usleep(1);
+ while (state != 6)
+ ;
+ /*
+ * Now we have no writer, but should still have data from the old
+ * writer. Check that we have a data-readable condition, and that
+ * the data can be read in the usual way.
+ */
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "6", 1, FD_ISSET(fd, &rfds));
+ if (read(fd, buf, sizeof buf) != 1)
+ err(1, "read");
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "6a", 1, FD_ISSET(fd, &rfds));
+ if (filetype == FT_FIFO) {
+ /*
+ * Check that the readable-data condition is sticky for a
+ * new reader and for the old reader. We really only have
+ * a hangup condition, but select() can only see this as
+ * a readable-data condition for null data. select()
+ * cannot distinguish this state from the initial state
+ * where there is a reader but has never been a writer, so
+ * the following tests (to follow the pattern in pipepoll.c)
+ * essentially test state 0 again.
+ */
+ fd2 = open(FIFONAME, O_RDONLY | O_NONBLOCK);
+ if (fd2 < 0)
+ err(1, "open for read");
+ fd1 = fd;
+ fd = fd2;
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "6b", 1, FD_ISSET(fd, &rfds));
+ fd = fd1;
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "6c", 1, FD_ISSET(fd, &rfds));
+ close(fd2);
+ SETUP(fd, rfds, tv);
+ if (select(fd + 1, &rfds, NULL, NULL, &tv) < 0)
+ err(1, "select");
+ report(num++, "6d", 1, FD_ISSET(fd, &rfds));
+ }
+ close(fd);
+ kill(ppid, SIGUSR1);
+
+ exit(0);
+}
+
+static void
+parent(int fd)
+{
+ usleep(1);
+ while (state != 1)
+ ;
+ if (filetype == FT_FIFO) {
+ fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
+ if (fd < 0)
+ err(1, "open for write");
+ }
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 2)
+ ;
+ if (write(fd, "", 1) != 1)
+ err(1, "write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 3)
+ ;
+ if (close(fd) != 0)
+ err(1, "close for write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 4)
+ ;
+ if (filetype != FT_FIFO)
+ return;
+ fd = open(FIFONAME, O_WRONLY | O_NONBLOCK);
+ if (fd < 0)
+ err(1, "open for write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 5)
+ ;
+ if (write(fd, "", 1) != 1)
+ err(1, "write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 6)
+ ;
+ if (close(fd) != 0)
+ err(1, "close for write");
+ kill(cpid, SIGUSR1);
+
+ usleep(1);
+ while (state != 7)
+ ;
+}
+
+int
+main(void)
+{
+ int fd[2], num;
+
+ num = 1;
+ printf("1..20\n");
+ fflush(stdout);
+ signal(SIGUSR1, catch);
+ ppid = getpid();
+ for (filetype = 0; filetype < FT_END; filetype++) {
+ switch (filetype) {
+ case FT_FIFO:
+ if (mkfifo(FIFONAME, 0666) != 0)
+ err(1, "mkfifo");
+ fd[0] = -1;
+ fd[1] = -1;
+ break;
+ case FT_SOCKETPAIR:
+ if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC,
+ fd) != 0)
+ err(1, "socketpair");
+ break;
+ case FT_PIPE:
+ if (pipe(fd) != 0)
+ err(1, "pipe");
+ break;
+ }
+ state = 0;
+ switch (cpid = fork()) {
+ case -1:
+ err(1, "fork");
+ case 0:
+ (void)close(fd[1]);
+ child(fd[0], num);
+ break;
+ default:
+ (void)close(fd[0]);
+ parent(fd[1]);
+ break;
+ }
+ num += filetype == FT_FIFO ? 12 : 4;
+ }
+ (void)unlink(FIFONAME);
+ return (0);
+}
OpenPOWER on IntegriCloud