diff options
Diffstat (limited to 'test/exit-no-cleanup.c')
-rw-r--r-- | test/exit-no-cleanup.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/test/exit-no-cleanup.c b/test/exit-no-cleanup.c new file mode 100644 index 0000000..b3fd5a4 --- /dev/null +++ b/test/exit-no-cleanup.c @@ -0,0 +1,117 @@ +/* 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; + + if (argc > 1) + return 0; + + 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); +} |