/* SPDX-License-Identifier: MIT */ /* * Description: test that thread pool issued requests don't cancel on thread * exit, but do get canceled once the parent exits. Do both * writes that finish and a poll request that sticks around. * */ #include #include #include #include #include #include #include #include #include "helpers.h" #include "liburing.h" #define NR_IOS 8 #define WSIZE 512 struct d { int fd; struct io_uring *ring; unsigned long off; int pipe_fd; int err; int i; }; static char *g_buf[NR_IOS] = {NULL}; static void free_g_buf(void) { int i; for (i = 0; i < NR_IOS; i++) free(g_buf[i]); } static void *do_io(void *data) { struct d *d = data; struct io_uring_sqe *sqe; char *buffer; int ret; buffer = t_malloc(WSIZE); g_buf[d->i] = buffer; memset(buffer, 0x5a, WSIZE); sqe = io_uring_get_sqe(d->ring); if (!sqe) { d->err++; return NULL; } io_uring_prep_write(sqe, d->fd, buffer, WSIZE, d->off); sqe->user_data = d->off; sqe = io_uring_get_sqe(d->ring); if (!sqe) { d->err++; return NULL; } io_uring_prep_poll_add(sqe, d->pipe_fd, POLLIN); ret = io_uring_submit(d->ring); if (ret != 2) d->err++; return NULL; } int main(int argc, char *argv[]) { struct io_uring ring; const char *fname; pthread_t thread; int ret, do_unlink, i, fd; struct d d; int fds[2]; if (pipe(fds) < 0) { perror("pipe"); return 1; } ret = io_uring_queue_init(32, &ring, 0); if (ret) { fprintf(stderr, "ring setup failed\n"); return 1; } if (argc > 1) { fname = argv[1]; do_unlink = 0; } else { fname = ".thread.exit"; do_unlink = 1; t_create_file(fname, 4096); } fd = open(fname, O_WRONLY); if (do_unlink) unlink(fname); if (fd < 0) { if (errno == EPERM || errno == EACCES) goto skip; perror("open"); return 1; } d.fd = fd; d.ring = ˚ d.off = 0; d.pipe_fd = fds[0]; d.err = 0; for (i = 0; i < NR_IOS; i++) { d.i = i; memset(&thread, 0, sizeof(thread)); pthread_create(&thread, NULL, do_io, &d); pthread_join(thread, NULL); d.off += WSIZE; } for (i = 0; i < NR_IOS; i++) { struct io_uring_cqe *cqe; ret = io_uring_wait_cqe(&ring, &cqe); if (ret) { fprintf(stderr, "io_uring_wait_cqe=%d\n", ret); goto err; } if (cqe->res != WSIZE) { fprintf(stderr, "cqe->res=%d, Expected %d\n", cqe->res, WSIZE); goto err; } io_uring_cqe_seen(&ring, cqe); } free_g_buf(); return d.err; err: free_g_buf(); return 1; skip: free_g_buf(); return T_EXIT_SKIP; }