blob: 722edbc57e6d53099027abe47ea18466b70b0a9c [file] [log] [blame]
/* 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 <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <pthread.h>
#include "liburing.h"
#define NR_IOS 8
#define WSIZE 512
static int create_file(const char *file, size_t size)
{
ssize_t ret;
char *buf;
int fd;
buf = malloc(size);
memset(buf, 0xaa, size);
fd = open(file, O_WRONLY | O_CREAT, 0644);
if (fd < 0) {
perror("open file");
return 1;
}
ret = write(fd, buf, size);
close(fd);
free(buf);
return ret != size;
}
struct d {
int fd;
struct io_uring *ring;
unsigned long off;
int pipe_fd;
int err;
};
static void *do_io(void *data)
{
struct d *d = data;
struct io_uring_sqe *sqe;
char *buffer;
int ret;
buffer = malloc(WSIZE);
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++;
free(buffer);
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;
}
if (do_unlink && create_file(fname, 4096)) {
fprintf(stderr, "file create failed\n");
return 1;
}
fd = open(fname, O_WRONLY);
if (fd < 0) {
perror("open");
return 1;
}
d.fd = fd;
d.ring = &ring;
d.off = 0;
d.pipe_fd = fds[0];
d.err = 0;
for (i = 0; i < NR_IOS; 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);
}
if (do_unlink)
unlink(fname);
return d.err;
err:
if (do_unlink)
unlink(fname);
return 1;
}