1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Based on a test case from Josef Grieb - test that we can exit without
4 * hanging if we have the task file table pinned by a request that is linked
5 * to another request that doesn't finish.
6 */
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <netinet/in.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <strings.h>
14 #include <sys/socket.h>
15 #include <unistd.h>
16 #include <poll.h>
17 #include "liburing.h"
18 #include "helpers.h"
19
20 #define BACKLOG 512
21
22 static struct io_uring ring;
23
add_poll(struct io_uring * ring,int fd)24 static void add_poll(struct io_uring *ring, int fd)
25 {
26 struct io_uring_sqe *sqe;
27
28 sqe = io_uring_get_sqe(ring);
29 io_uring_prep_poll_add(sqe, fd, POLLIN);
30 sqe->flags |= IOSQE_IO_LINK;
31 }
32
add_accept(struct io_uring * ring,int fd)33 static void add_accept(struct io_uring *ring, int fd)
34 {
35 struct io_uring_sqe *sqe;
36
37 sqe = io_uring_get_sqe(ring);
38 io_uring_prep_accept(sqe, fd, 0, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
39 }
40
setup_io_uring(void)41 static int setup_io_uring(void)
42 {
43 int ret;
44
45 ret = io_uring_queue_init(16, &ring, 0);
46 if (ret) {
47 fprintf(stderr, "Unable to setup io_uring: %s\n", strerror(-ret));
48 return 1;
49 }
50
51 return 0;
52 }
53
alarm_sig(int sig)54 static void alarm_sig(int sig)
55 {
56 exit(0);
57 }
58
main(int argc,char * argv[])59 int main(int argc, char *argv[])
60 {
61 struct sockaddr_in serv_addr;
62 struct io_uring_cqe *cqe;
63 int ret, sock_listen_fd;
64 const int val = 1;
65
66 if (argc > 1)
67 return T_EXIT_SKIP;
68
69 sock_listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
70 if (sock_listen_fd < 0) {
71 perror("socket");
72 return T_EXIT_FAIL;
73 }
74
75 setsockopt(sock_listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
76
77 memset(&serv_addr, 0, sizeof(serv_addr));
78 serv_addr.sin_family = AF_INET;
79 serv_addr.sin_addr.s_addr = INADDR_ANY;
80
81 if (t_bind_ephemeral_port(sock_listen_fd, &serv_addr)) {
82 perror("bind");
83 return T_EXIT_FAIL;
84 }
85
86 if (listen(sock_listen_fd, BACKLOG) < 0) {
87 perror("Error listening on socket\n");
88 return T_EXIT_FAIL;
89 }
90
91 if (setup_io_uring())
92 return T_EXIT_FAIL;
93
94 add_poll(&ring, sock_listen_fd);
95 add_accept(&ring, sock_listen_fd);
96
97 ret = io_uring_submit(&ring);
98 if (ret != 2) {
99 fprintf(stderr, "submit=%d\n", ret);
100 return T_EXIT_FAIL;
101 }
102
103 signal(SIGALRM, alarm_sig);
104 alarm(1);
105
106 ret = io_uring_wait_cqe(&ring, &cqe);
107 if (ret) {
108 fprintf(stderr, "wait_cqe=%d\n", ret);
109 return T_EXIT_FAIL;
110 }
111
112 io_uring_queue_exit(&ring);
113 return T_EXIT_PASS;
114 }
115