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, ¶ms);
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