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)
This commit is contained in:
parent
529ab57b9a
commit
5861f96654
21
tools/regression/poll/4/pipepoll.out
Normal file
21
tools/regression/poll/4/pipepoll.out
Normal file
@ -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
|
21
tools/regression/poll/4/pipeselect.out
Normal file
21
tools/regression/poll/4/pipeselect.out
Normal file
@ -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
|
21
tools/regression/poll/7/pipepoll.out
Normal file
21
tools/regression/poll/7/pipepoll.out
Normal file
@ -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
|
21
tools/regression/poll/7/pipeselect.out
Normal file
21
tools/regression/poll/7/pipeselect.out
Normal file
@ -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
|
35
tools/regression/poll/Makefile
Normal file
35
tools/regression/poll/Makefile
Normal file
@ -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
|
18
tools/regression/poll/Readme
Normal file
18
tools/regression/poll/Readme
Normal file
@ -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)
|
21
tools/regression/poll/l/pipepoll.out
Normal file
21
tools/regression/poll/l/pipepoll.out
Normal file
@ -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
|
21
tools/regression/poll/l/pipeselect.out
Normal file
21
tools/regression/poll/l/pipeselect.out
Normal file
@ -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
|
21
tools/regression/poll/m/pipepoll.out
Normal file
21
tools/regression/poll/m/pipepoll.out
Normal file
@ -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
|
21
tools/regression/poll/m/pipeselect.out
Normal file
21
tools/regression/poll/m/pipeselect.out
Normal file
@ -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
|
21
tools/regression/poll/n/pipepoll.out
Normal file
21
tools/regression/poll/n/pipepoll.out
Normal file
@ -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
|
21
tools/regression/poll/n/pipeselect.out
Normal file
21
tools/regression/poll/n/pipeselect.out
Normal file
@ -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
|
302
tools/regression/poll/pipepoll.c
Normal file
302
tools/regression/poll/pipepoll.c
Normal file
@ -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);
|
||||
}
|
318
tools/regression/poll/pipeselect.c
Normal file
318
tools/regression/poll/pipeselect.c
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user