Add some tests for poll(2)/shutdown(2) interaction.
This commit is contained in:
parent
61f6986b07
commit
e9d90c5143
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196554
@ -3,14 +3,15 @@
|
|||||||
# Nothing yet works with gmake for the path to the sources.
|
# Nothing yet works with gmake for the path to the sources.
|
||||||
.PATH: ..
|
.PATH: ..
|
||||||
|
|
||||||
PROG= pipepoll pipeselect
|
PROG= pipepoll pipeselect sockpoll
|
||||||
CFLAGS+= -Werror -Wall
|
CFLAGS+= -Werror -Wall
|
||||||
|
|
||||||
all: ${PROG}
|
all: ${PROG}
|
||||||
pipepoll: pipepoll.c
|
pipepoll: pipepoll.c
|
||||||
pipeselect: pipeselect.c
|
pipeselect: pipeselect.c
|
||||||
|
sockpoll: sockpoll.c
|
||||||
|
|
||||||
pipepoll pipeselect:
|
pipepoll pipeselect sockpoll:
|
||||||
${CC} ${CFLAGS} ${LDFLAGS} -o $@ $@.c
|
${CC} ${CFLAGS} ${LDFLAGS} -o $@ $@.c
|
||||||
|
|
||||||
test: all
|
test: all
|
||||||
|
202
tools/regression/poll/sockpoll.c
Normal file
202
tools/regression/poll/sockpoll.c
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/* $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>
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
decode_events(int events)
|
||||||
|
{
|
||||||
|
char *ncresult;
|
||||||
|
const char *result;
|
||||||
|
|
||||||
|
switch (events) {
|
||||||
|
case POLLIN:
|
||||||
|
result = "POLLIN";
|
||||||
|
break;
|
||||||
|
case POLLOUT:
|
||||||
|
result = "POLLOUT";
|
||||||
|
break;
|
||||||
|
case POLLIN | POLLOUT:
|
||||||
|
result = "POLLIN | POLLOUT";
|
||||||
|
break;
|
||||||
|
case POLLHUP:
|
||||||
|
result = "POLLHUP";
|
||||||
|
break;
|
||||||
|
case POLLIN | POLLHUP:
|
||||||
|
result = "POLLIN | POLLHUP";
|
||||||
|
break;
|
||||||
|
case POLLOUT | POLLHUP:
|
||||||
|
result = "POLLOUT | POLLHUP";
|
||||||
|
break;
|
||||||
|
case POLLIN | POLLOUT | POLLHUP:
|
||||||
|
result = "POLLIN | POLLOUT | 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(" state %s: expected %s; got %s\n",
|
||||||
|
state, decode_events(expected), decode_events(got));
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_nonblocking(int sck)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
flags = fcntl(sck, F_GETFL, 0);
|
||||||
|
flags |= O_NONBLOCK;
|
||||||
|
|
||||||
|
if (fcntl(sck, F_SETFL, flags))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
|
||||||
|
static int fd[2];
|
||||||
|
static struct pollfd pfd0;
|
||||||
|
static struct pollfd pfd1;
|
||||||
|
|
||||||
|
void
|
||||||
|
setup(void)
|
||||||
|
{
|
||||||
|
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
|
||||||
|
err(1, "socketpair");
|
||||||
|
if (set_nonblocking(fd[0]) == -1)
|
||||||
|
err(1, "fcntl");
|
||||||
|
if (set_nonblocking(fd[1]) == -1)
|
||||||
|
err(1, "fcntl");
|
||||||
|
pfd0.fd = fd[0];
|
||||||
|
pfd0.events = POLLIN | POLLOUT;
|
||||||
|
pfd1.fd = fd[1];
|
||||||
|
pfd1.events = POLLIN | POLLOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
|
||||||
|
num = 1;
|
||||||
|
printf("1..18\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
/* Large write with close */
|
||||||
|
setup();
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "initial 0", POLLOUT, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "initial 1", POLLOUT, pfd1.revents);
|
||||||
|
if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
|
||||||
|
err(1, "write");
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after large write", 0, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents);
|
||||||
|
close(fd[0]);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
|
||||||
|
if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
|
||||||
|
err(1, "read");
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after reading input", POLLHUP, pfd1.revents);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
/* With shutdown(SHUT_WR) */
|
||||||
|
setup();
|
||||||
|
if (shutdown(fd[0], SHUT_WR) == -1)
|
||||||
|
err(1, "shutdown");
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
|
||||||
|
switch (read(fd[1], largeblock, sizeof(largeblock))) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
err(1, "read after other side shutdown");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errx(1, "kernel made up data that was never written");
|
||||||
|
}
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents);
|
||||||
|
if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
|
||||||
|
err(1, "write");
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after writing", POLLIN, pfd1.revents);
|
||||||
|
if (shutdown(fd[1], SHUT_WR) == -1)
|
||||||
|
err(1, "shutdown second");
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after second shutdown", POLLHUP, pfd1.revents);
|
||||||
|
close(fd[0]);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after close", POLLHUP, pfd1.revents);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With shutdown(SHUT_RD)
|
||||||
|
* Note that shutdown(SHUT_WR) is passed to the peer, but
|
||||||
|
* shutdown(SHUT_RD) is not.
|
||||||
|
*/
|
||||||
|
setup();
|
||||||
|
if (shutdown(fd[0], SHUT_RD) == -1)
|
||||||
|
err(1, "shutdown");
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents);
|
||||||
|
if (shutdown(fd[0], SHUT_WR) == -1)
|
||||||
|
err(1, "shutdown");
|
||||||
|
if (poll(&pfd0, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
|
||||||
|
if (poll(&pfd1, 1, 0) == -1)
|
||||||
|
err(1, "poll");
|
||||||
|
report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents);
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user