svn commit: r195636 - in head/tools/regression/poll: . 4 7 l m n

Konstantin Belousov kib at FreeBSD.org
Sun Jul 12 12:50:44 UTC 2009


Author: kib
Date: Sun Jul 12 12:50:43 2009
New Revision: 195636
URL: http://svn.freebsd.org/changeset/base/195636

Log:
  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)

Added:
  head/tools/regression/poll/
  head/tools/regression/poll/4/
  head/tools/regression/poll/4/pipepoll.out   (contents, props changed)
  head/tools/regression/poll/4/pipeselect.out   (contents, props changed)
  head/tools/regression/poll/7/
  head/tools/regression/poll/7/pipepoll.out   (contents, props changed)
  head/tools/regression/poll/7/pipeselect.out   (contents, props changed)
  head/tools/regression/poll/Makefile   (contents, props changed)
  head/tools/regression/poll/Readme   (contents, props changed)
  head/tools/regression/poll/l/
  head/tools/regression/poll/l/pipepoll.out   (contents, props changed)
  head/tools/regression/poll/l/pipeselect.out   (contents, props changed)
  head/tools/regression/poll/m/
  head/tools/regression/poll/m/pipepoll.out   (contents, props changed)
  head/tools/regression/poll/m/pipeselect.out   (contents, props changed)
  head/tools/regression/poll/n/
  head/tools/regression/poll/n/pipepoll.out   (contents, props changed)
  head/tools/regression/poll/n/pipeselect.out   (contents, props changed)
  head/tools/regression/poll/pipepoll.c   (contents, props changed)
  head/tools/regression/poll/pipeselect.c   (contents, props changed)

Added: head/tools/regression/poll/4/pipepoll.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/4/pipepoll.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/4/pipeselect.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/4/pipeselect.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/7/pipepoll.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/7/pipepoll.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/7/pipeselect.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/7/pipeselect.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/Makefile	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/Readme
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/Readme	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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)

Added: head/tools/regression/poll/l/pipepoll.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/l/pipepoll.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/l/pipeselect.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/l/pipeselect.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/m/pipepoll.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/m/pipepoll.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/m/pipeselect.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/m/pipeselect.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/n/pipepoll.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/n/pipepoll.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/n/pipeselect.out
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/n/pipeselect.out	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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

Added: head/tools/regression/poll/pipepoll.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/pipepoll.c	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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);
+}

Added: head/tools/regression/poll/pipeselect.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/poll/pipeselect.c	Sun Jul 12 12:50:43 2009	(r195636)
@@ -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);
+}


More information about the svn-src-head mailing list