summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2021-02-10 07:57:53 -0700
committerJens Axboe <axboe@kernel.dk>2021-02-10 08:03:56 -0700
commit7856addff134121860630a977bdd8a846c9f9187 (patch)
tree73416c165a5a4128717e4040cefaa57f8270e128
parent1313aaf5f1b025f1939d41af167688a10fb8ff04 (diff)
downloadliburing-7856addff134121860630a977bdd8a846c9f9187.tar.gz
liburing-7856addff134121860630a977bdd8a846c9f9187.tar.bz2
Add test case for circular reference SQPOLL hang
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--.gitignore1
-rw-r--r--test/Makefile2
-rw-r--r--test/sqpoll-exit-hang.c77
3 files changed, 80 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index f978b2f..d9fa2c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,6 +103,7 @@
/test/sq-poll-dup
/test/sq-poll-kthread
/test/sq-poll-share
+/test/sqpoll-exit-hang
/test/sqpoll-sleep
/test/sq-space_left
/test/statx
diff --git a/test/Makefile b/test/Makefile
index 5790087..157ff95 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -99,6 +99,7 @@ test_targets += \
sq-poll-dup \
sq-poll-kthread \
sq-poll-share \
+ sqpoll-exit-hang \
sqpoll-sleep \
sq-space_left \
stdout \
@@ -224,6 +225,7 @@ test_srcs := \
sq-poll-dup.c \
sq-poll-kthread.c \
sq-poll-share.c \
+ sqpoll-exit-hang.c \
sqpoll-sleep.c \
sq-space_left.c \
statx.c \
diff --git a/test/sqpoll-exit-hang.c b/test/sqpoll-exit-hang.c
new file mode 100644
index 0000000..43385ce
--- /dev/null
+++ b/test/sqpoll-exit-hang.c
@@ -0,0 +1,77 @@
+/*
+ * Test that we exit properly with SQPOLL and having a request that
+ * adds a circular reference to the ring itself.
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include "liburing.h"
+
+static unsigned long long mtime_since(const struct timeval *s,
+ const struct timeval *e)
+{
+ long long sec, usec;
+
+ sec = e->tv_sec - s->tv_sec;
+ usec = (e->tv_usec - s->tv_usec);
+ if (sec > 0 && usec < 0) {
+ sec--;
+ usec += 1000000;
+ }
+
+ sec *= 1000;
+ usec /= 1000;
+ return sec + usec;
+}
+
+static unsigned long long mtime_since_now(struct timeval *tv)
+{
+ struct timeval end;
+
+ gettimeofday(&end, NULL);
+ return mtime_since(tv, &end);
+}
+
+int main(int argc, char *argv[])
+{
+ struct io_uring_params p = {};
+ struct timeval tv;
+ struct io_uring ring;
+ struct io_uring_sqe *sqe;
+ int ret;
+
+ if (argc > 1)
+ return 0;
+
+ p.flags = IORING_SETUP_SQPOLL;
+ p.sq_thread_idle = 100;
+
+ ret = io_uring_queue_init_params(1, &ring, &p);
+ if (ret) {
+ if (geteuid()) {
+ printf("%s: skipped, not root\n", argv[0]);
+ return 0;
+ }
+ fprintf(stderr, "queue_init=%d\n", ret);
+ return 1;
+ }
+
+ if (!(p.features & IORING_FEAT_SQPOLL_NONFIXED)) {
+ fprintf(stdout, "Skipping\n");
+ return 0;
+ }
+
+ sqe = io_uring_get_sqe(&ring);
+ io_uring_prep_poll_add(sqe, ring.ring_fd, POLLIN);
+ io_uring_submit(&ring);
+
+ gettimeofday(&tv, NULL);
+ do {
+ usleep(1000);
+ } while (mtime_since_now(&tv) < 1000);
+
+ return 0;
+}