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
19 #define BACKLOG 512
20
21 #define PORT 9100
22
23 static struct io_uring ring;
24
add_poll(struct io_uring * ring,int fd)25 static void add_poll(struct io_uring *ring, int fd)
26 {
27 struct io_uring_sqe *sqe;
28
29 sqe = io_uring_get_sqe(ring);
30 io_uring_prep_poll_add(sqe, fd, POLLIN);
31 sqe->flags |= IOSQE_IO_LINK;
32 }
33
add_accept(struct io_uring * ring,int fd)34 static void add_accept(struct io_uring *ring, int fd)
35 {
36 struct io_uring_sqe *sqe;
37
38 sqe = io_uring_get_sqe(ring);
39 io_uring_prep_accept(sqe, fd, 0, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
40 }
41
setup_io_uring(void)42 static int setup_io_uring(void)
43 {
44 int ret;
45
46 ret = io_uring_queue_init(16, &ring, 0);
47 if (ret) {
48 fprintf(stderr, "Unable to setup io_uring: %s\n", strerror(-ret));
49 return 1;
50 }
51
52 return 0;
53 }
54
alarm_sig(int sig)55 static void alarm_sig(int sig)
56 {
57 exit(0);
58 }
59
main(int argc,char * argv[])60 int main(int argc, char *argv[])
61 {
62 struct sockaddr_in serv_addr;
63 struct io_uring_cqe *cqe;
64 int ret, sock_listen_fd;
65 const int val = 1;
66 int i;
67
68 if (argc > 1)
69 return 0;
70
71 sock_listen_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
72 if (sock_listen_fd < 0) {
73 perror("socket");
74 return 1;
75 }
76
77 setsockopt(sock_listen_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
78
79 memset(&serv_addr, 0, sizeof(serv_addr));
80 serv_addr.sin_family = AF_INET;
81 serv_addr.sin_addr.s_addr = INADDR_ANY;
82
83 for (i = 0; i < 100; i++) {
84 serv_addr.sin_port = htons(PORT + i);
85
86 ret = bind(sock_listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
87 if (!ret)
88 break;
89 if (errno != EADDRINUSE) {
90 fprintf(stderr, "bind: %s\n", strerror(errno));
91 return 1;
92 }
93 if (i == 99) {
94 printf("Gave up on finding a port, skipping\n");
95 goto out;
96 }
97 }
98
99 if (listen(sock_listen_fd, BACKLOG) < 0) {
100 perror("Error listening on socket\n");
101 return 1;
102 }
103
104 if (setup_io_uring())
105 return 1;
106
107 add_poll(&ring, sock_listen_fd);
108 add_accept(&ring, sock_listen_fd);
109
110 ret = io_uring_submit(&ring);
111 if (ret != 2) {
112 fprintf(stderr, "submit=%d\n", ret);
113 return 1;
114 }
115
116 signal(SIGALRM, alarm_sig);
117 alarm(1);
118
119 ret = io_uring_wait_cqe(&ring, &cqe);
120 if (ret) {
121 fprintf(stderr, "wait_cqe=%d\n", ret);
122 return 1;
123 }
124
125 out:
126 io_uring_queue_exit(&ring);
127 return 0;
128 }
129