summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2019-10-17 16:36:37 -0600
committerJens Axboe <axboe@kernel.dk>2019-10-17 16:36:37 -0600
commit79ba71a4881fb1cd300520553d7285b3c5ee1293 (patch)
tree7db512514bae24546321c70a5f9a97fbe70b48ac
parent08bd815170ab4352d71019f4d3e532cd3f6f0489 (diff)
downloadliburing-79ba71a4881fb1cd300520553d7285b3c5ee1293.tar.gz
liburing-79ba71a4881fb1cd300520553d7285b3c5ee1293.tar.bz2
Add deadlock socket read/write test case
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--test/Makefile5
-rw-r--r--test/socket-rw.c128
2 files changed, 131 insertions, 2 deletions
diff --git a/test/Makefile b/test/Makefile
index c02aad4..4354d88 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -7,7 +7,8 @@ all_targets += poll poll-cancel ring-leak fsync io_uring_setup io_uring_register
917257daa0fe-test b19062a56726-test eeed8b54e0df-test link \
send_recvmsg a4c0b3decb33-test 500f9fbadef8-test timeout \
sq-space_left stdout cq-ready cq-peek-batch file-register \
- cq-size 8a9973408177-test a0908ae19763-test 232c93d07b74-test
+ cq-size 8a9973408177-test a0908ae19763-test 232c93d07b74-test \
+ socket-rw
include ../Makefile.quiet
@@ -22,7 +23,7 @@ test_srcs := poll.c poll-cancel.c ring-leak.c fsync.c io_uring_setup.c \
eeed8b54e0df-test.c link.c send_recvmsg.c a4c0b3decb33-test.c \
500f9fbadef8-test.c timeout.c sq-space_left.c stdout.c cq-ready.c\
cq-peek-batch.c file-register.c cq-size.c 8a9973408177-test.c \
- a0908ae19763-test.c 232c93d07b74-test.c
+ a0908ae19763-test.c 232c93d07b74-test.c socket-rw.c
test_objs := $(patsubst %.c,%.ol,$(test_srcs))
diff --git a/test/socket-rw.c b/test/socket-rw.c
new file mode 100644
index 0000000..0feafd7
--- /dev/null
+++ b/test/socket-rw.c
@@ -0,0 +1,128 @@
+/*
+ * Check that a readv on a socket queued before a writev doesn't hang
+ * the processing.
+ *
+ * From Hrvoje Zeba <zeba.hrvoje@gmail.com>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+
+#include <liburing.h>
+
+//#define TCP
+
+int main(int argc, char *argv[])
+{
+ int p_fd[2];
+
+#ifdef TCP
+ int32_t recv_s0 = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
+
+ int32_t val = 1;
+ assert(setsockopt(recv_s0, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)) != -1);
+
+ struct sockaddr_in addr;
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0x0001;
+ addr.sin_addr.s_addr = 0x0100007fU;
+
+ assert(bind(recv_s0, (struct sockaddr*)&addr, sizeof(addr)) != -1);
+ assert(listen(recv_s0, 128) != -1);
+
+
+ p_fd[1] = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
+
+ val = 1;
+ assert(setsockopt(p_fd[1], IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) != -1);
+
+ int32_t flags = fcntl(p_fd[1], F_GETFL, 0);
+ assert(flags != -1);
+
+ flags |= O_NONBLOCK;
+ assert(fcntl(p_fd[1], F_SETFL, flags) != -1);
+
+ assert(connect(p_fd[1], (struct sockaddr*)&addr, sizeof(addr)) == -1);
+
+ flags = fcntl(p_fd[1], F_GETFL, 0);
+ assert(flags != -1);
+
+ flags &= ~O_NONBLOCK;
+ assert(fcntl(p_fd[1], F_SETFL, flags) != -1);
+
+ p_fd[0] = accept(recv_s0, NULL, NULL);
+ assert(p_fd[0] != -1);
+
+ while (1) {
+ int32_t code;
+ socklen_t code_len = sizeof(code);
+
+ assert(getsockopt(p_fd[1], SOL_SOCKET, SO_ERROR, &code, &code_len) != -1);
+
+ if (!code)
+ break;
+ }
+#else
+ assert(pipe(p_fd) != -1);
+#endif
+
+ struct io_uring m_io_uring;
+
+ assert(io_uring_queue_init(32, &m_io_uring, 0) >= 0);
+
+ char recv_buff[128];
+ char send_buff[128];
+
+ {
+ struct iovec iov[1];
+
+ iov[0].iov_base = recv_buff;
+ iov[0].iov_len = sizeof(recv_buff);
+
+ struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring);
+ assert(sqe != NULL);
+
+ io_uring_prep_readv(sqe, p_fd[0], iov, 1, 0);
+ }
+
+ {
+ struct iovec iov[1];
+
+ iov[0].iov_base = send_buff;
+ iov[0].iov_len = sizeof(send_buff);
+
+ struct io_uring_sqe* sqe = io_uring_get_sqe(&m_io_uring);
+ assert(sqe != NULL);
+
+ io_uring_prep_writev(sqe, p_fd[1], iov, 1, 0);
+ }
+
+ assert(io_uring_submit(&m_io_uring) != -1);
+
+ struct io_uring_cqe* cqe;
+ uint32_t head;
+ uint32_t count = 0;
+
+ while (count != 2) {
+ io_uring_for_each_cqe(&m_io_uring, head, cqe) {
+ assert(cqe->res == 128);
+ count++;
+ }
+
+ assert(count <= 2);
+ io_uring_cq_advance(&m_io_uring, count);
+ }
+
+ io_uring_queue_exit(&m_io_uring);
+ return 0;
+}