1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Description: test io_uring poll cancel handling
4 *
5 */
6 #include <errno.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <inttypes.h>
12 #include <sys/poll.h>
13 #include <sys/wait.h>
14 #include <sys/signal.h>
15
16 #include "liburing.h"
17
18 struct poll_data {
19 unsigned is_poll;
20 unsigned is_cancel;
21 };
22
sig_alrm(int sig)23 static void sig_alrm(int sig)
24 {
25 fprintf(stderr, "Timed out!\n");
26 exit(1);
27 }
28
main(int argc,char * argv[])29 int main(int argc, char *argv[])
30 {
31 struct io_uring ring;
32 int pipe1[2];
33 struct io_uring_cqe *cqe;
34 struct io_uring_sqe *sqe;
35 struct poll_data *pd, pds[2];
36 struct sigaction act;
37 int ret;
38
39 if (argc > 1)
40 return 0;
41
42 if (pipe(pipe1) != 0) {
43 perror("pipe");
44 return 1;
45 }
46
47 ret = io_uring_queue_init(2, &ring, 0);
48 if (ret) {
49 fprintf(stderr, "ring setup failed: %d\n", ret);
50 return 1;
51 }
52
53 memset(&act, 0, sizeof(act));
54 act.sa_handler = sig_alrm;
55 act.sa_flags = SA_RESTART;
56 sigaction(SIGALRM, &act, NULL);
57 alarm(1);
58
59 sqe = io_uring_get_sqe(&ring);
60 if (!sqe) {
61 fprintf(stderr, "get sqe failed\n");
62 return 1;
63 }
64
65 io_uring_prep_poll_add(sqe, pipe1[0], POLLIN);
66
67 pds[0].is_poll = 1;
68 pds[0].is_cancel = 0;
69 io_uring_sqe_set_data(sqe, &pds[0]);
70
71 ret = io_uring_submit(&ring);
72 if (ret <= 0) {
73 fprintf(stderr, "sqe submit failed\n");
74 return 1;
75 }
76
77 sqe = io_uring_get_sqe(&ring);
78 if (!sqe) {
79 fprintf(stderr, "get sqe failed\n");
80 return 1;
81 }
82
83 pds[1].is_poll = 0;
84 pds[1].is_cancel = 1;
85 io_uring_prep_poll_remove(sqe, &pds[0]);
86 io_uring_sqe_set_data(sqe, &pds[1]);
87
88 ret = io_uring_submit(&ring);
89 if (ret <= 0) {
90 fprintf(stderr, "sqe submit failed: %d\n", ret);
91 return 1;
92 }
93
94 ret = io_uring_wait_cqe(&ring, &cqe);
95 if (ret < 0) {
96 fprintf(stderr, "wait cqe failed: %d\n", ret);
97 return 1;
98 }
99
100 pd = io_uring_cqe_get_data(cqe);
101 if (pd->is_poll && cqe->res != -ECANCELED) {
102 fprintf(stderr ,"sqe (add=%d/remove=%d) failed with %ld\n",
103 pd->is_poll, pd->is_cancel,
104 (long) cqe->res);
105 return 1;
106 } else if (pd->is_cancel && cqe->res) {
107 fprintf(stderr, "sqe (add=%d/remove=%d) failed with %ld\n",
108 pd->is_poll, pd->is_cancel,
109 (long) cqe->res);
110 return 1;
111 }
112 io_uring_cqe_seen(&ring, cqe);
113
114 ret = io_uring_wait_cqe(&ring, &cqe);
115 if (ret < 0) {
116 fprintf(stderr, "wait_cqe: %d\n", ret);
117 return 1;
118 }
119
120 pd = io_uring_cqe_get_data(cqe);
121 if (pd->is_poll && cqe->res != -ECANCELED) {
122 fprintf(stderr, "sqe (add=%d/remove=%d) failed with %ld\n",
123 pd->is_poll, pd->is_cancel,
124 (long) cqe->res);
125 return 1;
126 } else if (pd->is_cancel && cqe->res) {
127 fprintf(stderr, "sqe (add=%d/remove=%d) failed with %ld\n",
128 pd->is_poll, pd->is_cancel,
129 (long) cqe->res);
130 return 1;
131 }
132
133 io_uring_cqe_seen(&ring, cqe);
134 return 0;
135 }
136