summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--test/Makefile2
-rw-r--r--test/exit-no-cleanup.c114
3 files changed, 117 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index cb08ca0..0a72f03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,6 +49,7 @@
/test/eventfd
/test/eventfd-disable
/test/eventfd-ring
+/test/exit-no-cleanup
/test/fadvise
/test/fallocate
/test/fc2a85cb02ef-test
diff --git a/test/Makefile b/test/Makefile
index c09078a..c70693c 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -67,6 +67,7 @@ test_srcs := \
eventfd-disable.c \
eventfd-ring.c \
exec-target.c \
+ exit-no-cleanup.c \
fadvise.c \
fallocate.c \
fc2a85cb02ef-test.c \
@@ -215,6 +216,7 @@ timeout-new: override LDFLAGS += -lpthread
thread-exit: override LDFLAGS += -lpthread
ring-leak2: override LDFLAGS += -lpthread
poll-mshot-update: override LDFLAGS += -lpthread
+exit-no-cleanup: override LDFLAGS += -lpthread
install: $(test_targets) runtests.sh runtests-loop.sh
$(INSTALL) -D -d -m 755 $(datadir)/liburing-test/
diff --git a/test/exit-no-cleanup.c b/test/exit-no-cleanup.c
new file mode 100644
index 0000000..90ef394
--- /dev/null
+++ b/test/exit-no-cleanup.c
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Test case testing exit without cleanup and io-wq work pending or queued.
+ *
+ * From Florian Fischer <florian.fl.fischer@fau.de>
+ * Link: https://lore.kernel.org/io-uring/20211202165606.mqryio4yzubl7ms5@pasture/
+ *
+ */
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/sysinfo.h>
+#include <unistd.h>
+
+#include "liburing.h"
+#include "helpers.h"
+
+#define IORING_ENTRIES 8
+
+static pthread_t *threads;
+static pthread_barrier_t init_barrier;
+static int sleep_fd, notify_fd;
+static sem_t sem;
+
+void *thread_func(void *arg)
+{
+ struct io_uring ring;
+ int res;
+
+ res = io_uring_queue_init(IORING_ENTRIES, &ring, 0);
+ if (res)
+ err(EXIT_FAILURE, "io_uring_queue_init failed");
+
+ pthread_barrier_wait(&init_barrier);
+
+ for(;;) {
+ struct io_uring_cqe *cqe;
+ struct io_uring_sqe *sqe;
+ uint64_t buf;
+ int res;
+
+ sqe = io_uring_get_sqe(&ring);
+ assert(sqe);
+
+ io_uring_prep_read(sqe, sleep_fd, &buf, sizeof(buf), 0);
+
+ res = io_uring_submit_and_wait(&ring, 1);
+ if (res < 0)
+ err(EXIT_FAILURE, "io_uring_submit_and_wait failed");
+
+ res = io_uring_peek_cqe(&ring, &cqe);
+ assert(!res);
+ if (cqe->res < 0) {
+ errno = -cqe->res;
+ err(EXIT_FAILURE, "read failed");
+ }
+ assert(cqe->res == sizeof(buf));
+
+ sem_post(&sem);
+
+ io_uring_cqe_seen(&ring, cqe);
+ }
+
+ return NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ int res, fds[2], i, cpus;
+ const uint64_t n = 0x42;
+
+ cpus = get_nprocs();
+ res = pthread_barrier_init(&init_barrier, NULL, cpus);
+ if (res)
+ err(EXIT_FAILURE, "pthread_barrier_init failed");
+
+ res = sem_init(&sem, 0, 0);
+ if (res)
+ err(EXIT_FAILURE, "sem_init failed");
+
+ threads = t_malloc(sizeof(pthread_t) * cpus);
+
+ res = pipe(fds);
+ if (res)
+ err(EXIT_FAILURE, "pipe failed");
+
+ sleep_fd = fds[0];
+ notify_fd = fds[1];
+
+ for (i = 0; i < cpus; i++) {
+ errno = pthread_create(&threads[i], NULL, thread_func, NULL);
+ if (errno)
+ err(EXIT_FAILURE, "pthread_create failed");
+ }
+
+ // Write #cpus notifications
+ for (i = 0; i < cpus; i++) {
+ res = write(notify_fd, &n, sizeof(n));
+ if (res < 0)
+ err(EXIT_FAILURE, "write failed");
+ assert(res == sizeof(n));
+ }
+
+ // Await that all notifications were received
+ for (i = 0; i < cpus; i++)
+ sem_wait(&sem);
+
+ // Exit without resource cleanup
+ exit(EXIT_SUCCESS);
+}