xref: /aosp_15_r20/external/liburing/test/read-before-exit.c (revision 25da2bea747f3a93b4c30fd9708b0618ef55a0e6)
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test if issuing IO from thread and immediately exiting will
4  * proceed correctly.
5  *
6  * Original test case from: https://github.com/axboe/liburing/issues/582
7  */
8 #include <unistd.h>
9 #include <pthread.h>
10 #include <sys/timerfd.h>
11 #include <string.h>
12 #include <stdio.h>
13 
14 #include "liburing.h"
15 #include "helpers.h"
16 
17 struct data {
18         struct io_uring *ring;
19         int timer_fd1;
20         int timer_fd2;
21         uint64_t buf1;
22         uint64_t buf2;
23 };
24 
submit(void * data)25 void *submit(void *data)
26 {
27 	struct io_uring_sqe *sqe;
28 	struct data *d = data;
29 	int ret;
30 
31 	sqe = io_uring_get_sqe(d->ring);
32 	io_uring_prep_read(sqe, d->timer_fd1, &d->buf1, sizeof(d->buf1), 0);
33 
34 	sqe = io_uring_get_sqe(d->ring);
35 	io_uring_prep_read(sqe, d->timer_fd2, &d->buf2, sizeof(d->buf2), 0);
36 
37 	ret = io_uring_submit(d->ring);
38 	if (ret != 2)
39 		return (void *) (uintptr_t) 1;
40 
41 	/* Exit suddenly. */
42 	return NULL;
43 }
44 
test(int flags)45 static int test(int flags)
46 {
47 	struct io_uring_params params = { .flags = flags, };
48 	struct io_uring ring;
49 	struct data d = { .ring = &ring, };
50 	pthread_t thread;
51 	void *res;
52 	int ret;
53 
54 	ret = t_create_ring_params(8, &ring, &params);
55 	if (ret == T_SETUP_SKIP)
56 		return 0;
57 	else if (ret != T_SETUP_OK)
58 		return 1;
59 
60 	d.timer_fd1 = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
61 	if (d.timer_fd1 < 0) {
62 		perror("timerfd_create");
63 		return 1;
64 	}
65 	d.timer_fd2 = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
66 	if (d.timer_fd2 < 0) {
67 		perror("timerfd_create");
68 		return 1;
69 	}
70 
71 	pthread_create(&thread, NULL, submit, &d);
72 	pthread_join(thread, &res);
73 
74 	/** Wait for completions and do stuff ...  **/
75 
76 	io_uring_queue_exit(&ring);
77 
78 	close(d.timer_fd1);
79 	close(d.timer_fd2);
80 	return !!res;
81 }
82 
main(int argc,char * argv[])83 int main(int argc, char *argv[])
84 {
85 	int ret, i;
86 
87 	for (i = 0; i < 1000; i++) {
88 		ret = test(0);
89 		if (ret) {
90 			fprintf(stderr, "Test failed\n");
91 			return ret;
92 		}
93 	}
94 
95 	for (i = 0; i < 1000; i++) {
96 		ret = test(IORING_SETUP_IOPOLL);
97 		if (ret) {
98 			fprintf(stderr, "Test IOPOLL failed\n");
99 			return ret;
100 		}
101 	}
102 
103 	for (i = 0; i < 100; i++) {
104 		ret = test(IORING_SETUP_SQPOLL);
105 		if (ret) {
106 			fprintf(stderr, "Test SQPOLL failed\n");
107 			return ret;
108 		}
109 	}
110 
111 	return 0;
112 }
113