xref: /aosp_15_r20/external/liburing/test/thread-exit.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
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 = &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