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 <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 int i;
30 };
31
32 static char *g_buf[NR_IOS] = {NULL};
33
free_g_buf(void)34 static void free_g_buf(void)
35 {
36 int i;
37 for (i = 0; i < NR_IOS; i++)
38 free(g_buf[i]);
39 }
40
do_io(void * data)41 static void *do_io(void *data)
42 {
43 struct d *d = data;
44 struct io_uring_sqe *sqe;
45 char *buffer;
46 int ret;
47
48 buffer = t_malloc(WSIZE);
49 g_buf[d->i] = buffer;
50 memset(buffer, 0x5a, WSIZE);
51 sqe = io_uring_get_sqe(d->ring);
52 if (!sqe) {
53 d->err++;
54 return NULL;
55 }
56 io_uring_prep_write(sqe, d->fd, buffer, WSIZE, d->off);
57 sqe->user_data = d->off;
58
59 sqe = io_uring_get_sqe(d->ring);
60 if (!sqe) {
61 d->err++;
62 return NULL;
63 }
64 io_uring_prep_poll_add(sqe, d->pipe_fd, POLLIN);
65
66 ret = io_uring_submit(d->ring);
67 if (ret != 2)
68 d->err++;
69 return NULL;
70 }
71
main(int argc,char * argv[])72 int main(int argc, char *argv[])
73 {
74 struct io_uring ring;
75 const char *fname;
76 pthread_t thread;
77 int ret, do_unlink, i, fd;
78 struct d d;
79 int fds[2];
80
81 if (pipe(fds) < 0) {
82 perror("pipe");
83 return 1;
84 }
85
86 ret = io_uring_queue_init(32, &ring, 0);
87 if (ret) {
88 fprintf(stderr, "ring setup failed\n");
89 return 1;
90 }
91
92 if (argc > 1) {
93 fname = argv[1];
94 do_unlink = 0;
95 } else {
96 fname = ".thread.exit";
97 do_unlink = 1;
98 t_create_file(fname, 4096);
99 }
100
101 fd = open(fname, O_WRONLY);
102 if (do_unlink)
103 unlink(fname);
104 if (fd < 0) {
105 perror("open");
106 return 1;
107 }
108
109 d.fd = fd;
110 d.ring = ˚
111 d.off = 0;
112 d.pipe_fd = fds[0];
113 d.err = 0;
114 for (i = 0; i < NR_IOS; i++) {
115 d.i = i;
116 memset(&thread, 0, sizeof(thread));
117 pthread_create(&thread, NULL, do_io, &d);
118 pthread_join(thread, NULL);
119 d.off += WSIZE;
120 }
121
122 for (i = 0; i < NR_IOS; i++) {
123 struct io_uring_cqe *cqe;
124
125 ret = io_uring_wait_cqe(&ring, &cqe);
126 if (ret) {
127 fprintf(stderr, "io_uring_wait_cqe=%d\n", ret);
128 goto err;
129 }
130 if (cqe->res != WSIZE) {
131 fprintf(stderr, "cqe->res=%d, Expected %d\n", cqe->res,
132 WSIZE);
133 goto err;
134 }
135 io_uring_cqe_seen(&ring, cqe);
136 }
137
138 free_g_buf();
139 return d.err;
140 err:
141 free_g_buf();
142 return 1;
143 }
144