aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-09-17 16:31:59 +0000
committerMark Johnston <markj@FreeBSD.org>2021-09-17 18:19:06 +0000
commitc13f6dd7d213cf08a26ed9a08290e239b49c25c4 (patch)
tree9925fa8a648d11f582935450d98017be9522c7cd
parentade1daa5c0d66b9086f9066297ed984932b5e212 (diff)
downloadsrc-c13f6dd7d213cf08a26ed9a08290e239b49c25c4.tar.gz
src-c13f6dd7d213cf08a26ed9a08290e239b49c25c4.zip
aio_test: Validate interactions between AIO on sockets and shutdown(2)
Reviewed by: asomers, jhb Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D31976
-rw-r--r--tests/sys/aio/aio_test.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/tests/sys/aio/aio_test.c b/tests/sys/aio/aio_test.c
index a81cb906e38a..c3cf1d372e23 100644
--- a/tests/sys/aio/aio_test.c
+++ b/tests/sys/aio/aio_test.c
@@ -54,6 +54,7 @@
#include <libutil.h>
#include <limits.h>
#include <semaphore.h>
+#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -1319,6 +1320,72 @@ ATF_TC_BODY(aio_socket_short_write_cancel, tc)
close(s[0]);
}
+/*
+ * Test handling of aio_read() and aio_write() on shut-down sockets.
+ */
+ATF_TC_WITHOUT_HEAD(aio_socket_shutdown);
+ATF_TC_BODY(aio_socket_shutdown, tc)
+{
+ struct aiocb iocb;
+ sigset_t set;
+ char *buffer;
+ ssize_t len;
+ size_t bsz;
+ int error, s[2];
+
+ ATF_REQUIRE_KERNEL_MODULE("aio");
+
+ ATF_REQUIRE(socketpair(PF_UNIX, SOCK_STREAM, 0, s) != -1);
+
+ bsz = 1024;
+ buffer = malloc(bsz);
+ memset(buffer, 0, bsz);
+
+ /* Put some data in s[0]'s recv buffer. */
+ ATF_REQUIRE(send(s[1], buffer, bsz, 0) == (ssize_t)bsz);
+
+ /* No more reading from s[0]. */
+ ATF_REQUIRE(shutdown(s[0], SHUT_RD) != -1);
+
+ ATF_REQUIRE(buffer != NULL);
+
+ memset(&iocb, 0, sizeof(iocb));
+ iocb.aio_fildes = s[0];
+ iocb.aio_buf = buffer;
+ iocb.aio_nbytes = bsz;
+ ATF_REQUIRE(aio_read(&iocb) == 0);
+
+ /* Expect to see zero bytes, analogous to recv(2). */
+ while ((error = aio_error(&iocb)) == EINPROGRESS)
+ usleep(25000);
+ ATF_REQUIRE_MSG(error == 0, "aio_error() returned %d", error);
+ len = aio_return(&iocb);
+ ATF_REQUIRE_MSG(len == 0, "read job returned %zd bytes", len);
+
+ /* No more writing to s[1]. */
+ ATF_REQUIRE(shutdown(s[1], SHUT_WR) != -1);
+
+ /* Block SIGPIPE so that we can detect the error in-band. */
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) == 0);
+
+ memset(&iocb, 0, sizeof(iocb));
+ iocb.aio_fildes = s[1];
+ iocb.aio_buf = buffer;
+ iocb.aio_nbytes = bsz;
+ ATF_REQUIRE(aio_write(&iocb) == 0);
+
+ /* Expect an error, analogous to send(2). */
+ while ((error = aio_error(&iocb)) == EINPROGRESS)
+ usleep(25000);
+ ATF_REQUIRE_MSG(error == EPIPE, "aio_error() returned %d", error);
+
+ ATF_REQUIRE(close(s[0]) != -1);
+ ATF_REQUIRE(close(s[1]) != -1);
+ free(buffer);
+}
+
/*
* test aio_fsync's behavior with bad inputs
*/
@@ -1885,6 +1952,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, aio_socket_listen_fail);
ATF_TP_ADD_TC(tp, aio_socket_listen_pending);
ATF_TP_ADD_TC(tp, aio_socket_short_write_cancel);
+ ATF_TP_ADD_TC(tp, aio_socket_shutdown);
ATF_TP_ADD_TC(tp, aio_writev_dos_iov_len);
ATF_TP_ADD_TC(tp, aio_writev_dos_iovcnt);
ATF_TP_ADD_TC(tp, aio_writev_efault);