1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: test that thread pool issued requests don't cancel on thread
4 * exit, but do get canceled once the parent exits. Do both
5 * writes that finish and a poll request that sticks around.
6 *
7 */
8 #include <errno.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <sys/poll.h>
15 #include <pthread.h>
16
17 #include "helpers.h"
18 #include "liburing.h"
19
20 #define NR_IOS 8
21 #define WSIZE 512
22
23 struct d {
24 int fd;
25 struct io_uring *ring;
26 unsigned long off;
27 int pipe_fd;
28 int err;
29 };
30
do_io(void * data)31 static void *do_io(void *data)
32 {
33 struct d *d = data;
34 struct io_uring_sqe *sqe;
35 char *buffer;
36 int ret;
37
38 buffer = t_malloc(WSIZE);
39 memset(buffer, 0x5a, WSIZE);
40 sqe = io_uring_get_sqe(d->ring);
41 if (!sqe) {
42 d->err++;
43 return NULL;
44 }
45 io_uring_prep_write(sqe, d->fd, buffer, WSIZE, d->off);
46 sqe->user_data = d->off;
47
48 sqe = io_uring_get_sqe(d->ring);
49 if (!sqe) {
50 d->err++;
51 return NULL;
52 }
53 io_uring_prep_poll_add(sqe, d->pipe_fd, POLLIN);
54
55 ret = io_uring_submit(d->ring);
56 if (ret != 2)
57 d->err++;
58
59 free(buffer);
60 return NULL;
61 }
62
main(int argc,char * argv[])63 int main(int argc, char *argv[])
64 {
65 struct io_uring ring;
66 const char *fname;
67 pthread_t thread;
68 int ret, do_unlink, i, fd;
69 struct d d;
70 int fds[2];
71
72 if (pipe(fds) < 0) {
73 perror("pipe");
74 return 1;
75 }
76
77 ret = io_uring_queue_init(32, &ring, 0);
78 if (ret) {
79 fprintf(stderr, "ring setup failed\n");
80 return 1;
81 }
82
83 if (argc > 1) {
84 fname = argv[1];
85 do_unlink = 0;
86 } else {
87 fname = ".thread.exit";
88 do_unlink = 1;
89 }
90
91 if (do_unlink)
92 t_create_file(fname, 4096);
93
94 fd = open(fname, O_WRONLY);
95 if (fd < 0) {
96 perror("open");
97 return 1;
98 }
99
100 d.fd = fd;
101 d.ring = ˚
102 d.off = 0;
103 d.pipe_fd = fds[0];
104 d.err = 0;
105 for (i = 0; i < NR_IOS; i++) {
106 memset(&thread, 0, sizeof(thread));
107 pthread_create(&thread, NULL, do_io, &d);
108 pthread_join(thread, NULL);
109 d.off += WSIZE;
110 }
111
112 for (i = 0; i < NR_IOS; i++) {
113 struct io_uring_cqe *cqe;
114
115 ret = io_uring_wait_cqe(&ring, &cqe);
116 if (ret) {
117 fprintf(stderr, "io_uring_wait_cqe=%d\n", ret);
118 goto err;
119 }
120 if (cqe->res != WSIZE) {
121 fprintf(stderr, "cqe->res=%d, Expected %d\n", cqe->res,
122 WSIZE);
123 goto err;
124 }
125 io_uring_cqe_seen(&ring, cqe);
126 }
127
128 if (do_unlink)
129 unlink(fname);
130 return d.err;
131 err:
132 if (do_unlink)
133 unlink(fname);
134 return 1;
135 }
136