• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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