1 /* SPDX-License-Identifier: MIT */
2 /*
3 * Check that IORING_OP_ACCEPT works, and send some data across to verify we
4 * didn't get a junk fd.
5 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <assert.h>
10 #include <limits.h>
11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <sys/socket.h>
16 #include <sys/time.h>
17 #include <sys/resource.h>
18 #include <sys/un.h>
19 #include <netinet/tcp.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22
23 #include "helpers.h"
24 #include "liburing.h"
25
26 #define MAX_FDS 32
27 static int no_accept;
28 static int no_accept_multi;
29
30 struct data {
31 char buf[128];
32 struct iovec iov;
33 };
34
35 struct accept_test_args {
36 int accept_should_error;
37 bool fixed;
38 bool nonblock;
39 bool queue_accept_before_connect;
40 bool multishot;
41 int extra_loops;
42 };
43
close_fds(int fds[],int nr)44 static void close_fds(int fds[], int nr)
45 {
46 int i;
47
48 for (i = 0; i < nr; i++)
49 close(fds[i]);
50 }
51
close_sock_fds(int s_fd[],int c_fd[],int nr,bool fixed)52 static void close_sock_fds(int s_fd[], int c_fd[], int nr, bool fixed)
53 {
54 if (!fixed)
55 close_fds(s_fd, nr);
56 close_fds(c_fd, nr);
57 }
58
queue_send(struct io_uring * ring,int fd)59 static void queue_send(struct io_uring *ring, int fd)
60 {
61 struct io_uring_sqe *sqe;
62 struct data *d;
63
64 d = t_malloc(sizeof(*d));
65 d->iov.iov_base = d->buf;
66 d->iov.iov_len = sizeof(d->buf);
67
68 sqe = io_uring_get_sqe(ring);
69 io_uring_prep_writev(sqe, fd, &d->iov, 1, 0);
70 sqe->user_data = 1;
71 }
72
queue_recv(struct io_uring * ring,int fd,bool fixed)73 static void queue_recv(struct io_uring *ring, int fd, bool fixed)
74 {
75 struct io_uring_sqe *sqe;
76 struct data *d;
77
78 d = t_malloc(sizeof(*d));
79 d->iov.iov_base = d->buf;
80 d->iov.iov_len = sizeof(d->buf);
81
82 sqe = io_uring_get_sqe(ring);
83 io_uring_prep_readv(sqe, fd, &d->iov, 1, 0);
84 sqe->user_data = 2;
85 if (fixed)
86 sqe->flags |= IOSQE_FIXED_FILE;
87 }
88
queue_accept_conn(struct io_uring * ring,int fd,struct accept_test_args args)89 static void queue_accept_conn(struct io_uring *ring, int fd,
90 struct accept_test_args args)
91 {
92 struct io_uring_sqe *sqe;
93 int ret;
94 int fixed_idx = args.fixed ? 0 : -1;
95 int count = 1 + args.extra_loops;
96 bool multishot = args.multishot;
97
98 while (count--) {
99 sqe = io_uring_get_sqe(ring);
100 if (fixed_idx < 0) {
101 if (!multishot)
102 io_uring_prep_accept(sqe, fd, NULL, NULL, 0);
103 else
104 io_uring_prep_multishot_accept(sqe, fd, NULL,
105 NULL, 0);
106 } else {
107 if (!multishot)
108 io_uring_prep_accept_direct(sqe, fd, NULL, NULL,
109 0, fixed_idx);
110 else
111 io_uring_prep_multishot_accept_direct(sqe, fd,
112 NULL, NULL,
113 0);
114 }
115
116 ret = io_uring_submit(ring);
117 assert(ret != -1);
118 }
119 }
120
accept_conn(struct io_uring * ring,int fixed_idx,bool multishot)121 static int accept_conn(struct io_uring *ring, int fixed_idx, bool multishot)
122 {
123 struct io_uring_cqe *cqe;
124 int ret;
125
126 ret = io_uring_wait_cqe(ring, &cqe);
127 assert(!ret);
128 ret = cqe->res;
129 io_uring_cqe_seen(ring, cqe);
130
131 if (fixed_idx >= 0) {
132 if (ret > 0) {
133 if (!multishot) {
134 close(ret);
135 return -EINVAL;
136 }
137 } else if (!ret) {
138 ret = fixed_idx;
139 }
140 }
141 return ret;
142 }
143
start_accept_listen(struct sockaddr_in * addr,int port_off,int extra_flags)144 static int start_accept_listen(struct sockaddr_in *addr, int port_off,
145 int extra_flags)
146 {
147 int fd, ret;
148
149 fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC | extra_flags,
150 IPPROTO_TCP);
151
152 int32_t val = 1;
153 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
154 assert(ret != -1);
155 ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
156 assert(ret != -1);
157
158 struct sockaddr_in laddr;
159
160 if (!addr)
161 addr = &laddr;
162
163 addr->sin_family = AF_INET;
164 addr->sin_port = htons(0x1235 + port_off);
165 addr->sin_addr.s_addr = inet_addr("127.0.0.1");
166
167 ret = bind(fd, (struct sockaddr*)addr, sizeof(*addr));
168 assert(ret != -1);
169 ret = listen(fd, 128);
170 assert(ret != -1);
171
172 return fd;
173 }
174
set_client_fd(struct sockaddr_in * addr)175 static int set_client_fd(struct sockaddr_in *addr)
176 {
177 int32_t val;
178 int fd, ret;
179
180 fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
181
182 val = 1;
183 ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
184 assert(ret != -1);
185
186 int32_t flags = fcntl(fd, F_GETFL, 0);
187 assert(flags != -1);
188
189 flags |= O_NONBLOCK;
190 ret = fcntl(fd, F_SETFL, flags);
191 assert(ret != -1);
192
193 ret = connect(fd, (struct sockaddr *)addr, sizeof(*addr));
194 assert(ret == -1);
195
196 flags = fcntl(fd, F_GETFL, 0);
197 assert(flags != -1);
198
199 flags &= ~O_NONBLOCK;
200 ret = fcntl(fd, F_SETFL, flags);
201 assert(ret != -1);
202
203 return fd;
204 }
205
test_loop(struct io_uring * ring,struct accept_test_args args,int recv_s0,struct sockaddr_in * addr)206 static int test_loop(struct io_uring *ring,
207 struct accept_test_args args,
208 int recv_s0,
209 struct sockaddr_in *addr)
210 {
211 struct io_uring_cqe *cqe;
212 uint32_t head, count = 0;
213 int i, ret, s_fd[MAX_FDS], c_fd[MAX_FDS], done = 0;
214 bool fixed = args.fixed;
215 bool multishot = args.multishot;
216 uint32_t multishot_mask = 0;
217 int nr_fds = multishot ? MAX_FDS : 1;
218
219 for (i = 0; i < nr_fds; i++)
220 c_fd[i] = set_client_fd(addr);
221
222 if (!args.queue_accept_before_connect)
223 queue_accept_conn(ring, recv_s0, args);
224
225 for (i = 0; i < nr_fds; i++) {
226 s_fd[i] = accept_conn(ring, fixed ? 0 : -1, multishot);
227 if (s_fd[i] == -EINVAL) {
228 if (args.accept_should_error)
229 goto out;
230 fprintf(stdout,
231 "%s %s Accept not supported, skipping\n",
232 fixed ? "Fixed" : "",
233 multishot ? "Multishot" : "");
234 if (multishot)
235 no_accept_multi = 1;
236 else
237 no_accept = 1;
238 goto out;
239 } else if (s_fd[i] < 0) {
240 if (args.accept_should_error &&
241 (s_fd[i] == -EBADF || s_fd[i] == -EINVAL))
242 goto out;
243 fprintf(stderr, "%s %s Accept[%d] got %d\n",
244 fixed ? "Fixed" : "",
245 multishot ? "Multishot" : "",
246 i, s_fd[i]);
247 goto err;
248 }
249
250 if (multishot && fixed) {
251 if (s_fd[i] >= MAX_FDS) {
252 fprintf(stderr,
253 "Fixed Multishot Accept[%d] got outbound index: %d\n",
254 i, s_fd[i]);
255 goto err;
256 }
257 /*
258 * for fixed multishot accept test, the file slots
259 * allocated are [0, 32), this means we finally end up
260 * with each bit of a u32 being 1.
261 */
262 multishot_mask |= (1U << s_fd[i]);
263 }
264 }
265
266 if (multishot) {
267 if (fixed && (~multishot_mask != 0U)) {
268 fprintf(stderr, "Fixed Multishot Accept misses events\n");
269 goto err;
270 }
271 goto out;
272 }
273
274 queue_send(ring, c_fd[0]);
275 queue_recv(ring, s_fd[0], fixed);
276
277 ret = io_uring_submit_and_wait(ring, 2);
278 assert(ret != -1);
279
280 while (count < 2) {
281 io_uring_for_each_cqe(ring, head, cqe) {
282 if (cqe->res < 0) {
283 fprintf(stderr, "Got cqe res %d, user_data %i\n",
284 cqe->res, (int)cqe->user_data);
285 done = 1;
286 break;
287 }
288 assert(cqe->res == 128);
289 count++;
290 }
291
292 assert(count <= 2);
293 io_uring_cq_advance(ring, count);
294 if (done)
295 goto err;
296 }
297
298 out:
299 close_sock_fds(s_fd, c_fd, nr_fds, fixed);
300 return 0;
301 err:
302 close_sock_fds(s_fd, c_fd, nr_fds, fixed);
303 return 1;
304 }
305
test(struct io_uring * ring,struct accept_test_args args)306 static int test(struct io_uring *ring, struct accept_test_args args)
307 {
308 struct sockaddr_in addr;
309 int ret = 0;
310 int loop;
311 int32_t recv_s0 = start_accept_listen(&addr, 0,
312 args.nonblock ? O_NONBLOCK : 0);
313 if (args.queue_accept_before_connect)
314 queue_accept_conn(ring, recv_s0, args);
315 for (loop = 0; loop < 1 + args.extra_loops; loop++) {
316 ret = test_loop(ring, args, recv_s0, &addr);
317 if (ret)
318 break;
319 }
320
321 close(recv_s0);
322 return ret;
323 }
324
sig_alrm(int sig)325 static void sig_alrm(int sig)
326 {
327 exit(0);
328 }
329
test_accept_pending_on_exit(void)330 static int test_accept_pending_on_exit(void)
331 {
332 struct io_uring m_io_uring;
333 struct io_uring_cqe *cqe;
334 struct io_uring_sqe *sqe;
335 int fd, ret;
336
337 ret = io_uring_queue_init(32, &m_io_uring, 0);
338 assert(ret >= 0);
339
340 fd = start_accept_listen(NULL, 0, 0);
341
342 sqe = io_uring_get_sqe(&m_io_uring);
343 io_uring_prep_accept(sqe, fd, NULL, NULL, 0);
344 ret = io_uring_submit(&m_io_uring);
345 assert(ret != -1);
346
347 signal(SIGALRM, sig_alrm);
348 alarm(1);
349 ret = io_uring_wait_cqe(&m_io_uring, &cqe);
350 assert(!ret);
351 io_uring_cqe_seen(&m_io_uring, cqe);
352
353 io_uring_queue_exit(&m_io_uring);
354 return 0;
355 }
356
357 struct test_accept_many_args {
358 unsigned int usecs;
359 bool nonblock;
360 bool single_sock;
361 bool close_fds;
362 };
363
364 /*
365 * Test issue many accepts and see if we handle cancellation on exit
366 */
test_accept_many(struct test_accept_many_args args)367 static int test_accept_many(struct test_accept_many_args args)
368 {
369 struct io_uring m_io_uring;
370 struct io_uring_cqe *cqe;
371 struct io_uring_sqe *sqe;
372 unsigned long cur_lim;
373 struct rlimit rlim;
374 int *fds, i, ret;
375 unsigned int nr = 128;
376 int nr_socks = args.single_sock ? 1 : nr;
377
378 if (getrlimit(RLIMIT_NPROC, &rlim) < 0) {
379 perror("getrlimit");
380 return 1;
381 }
382
383 cur_lim = rlim.rlim_cur;
384 rlim.rlim_cur = nr / 4;
385
386 if (setrlimit(RLIMIT_NPROC, &rlim) < 0) {
387 perror("setrlimit");
388 return 1;
389 }
390
391 ret = io_uring_queue_init(2 * nr, &m_io_uring, 0);
392 assert(ret >= 0);
393
394 fds = t_calloc(nr_socks, sizeof(int));
395
396 for (i = 0; i < nr_socks; i++)
397 fds[i] = start_accept_listen(NULL, i,
398 args.nonblock ? O_NONBLOCK : 0);
399
400 for (i = 0; i < nr; i++) {
401 int sock_idx = args.single_sock ? 0 : i;
402 sqe = io_uring_get_sqe(&m_io_uring);
403 io_uring_prep_accept(sqe, fds[sock_idx], NULL, NULL, 0);
404 sqe->user_data = 1 + i;
405 ret = io_uring_submit(&m_io_uring);
406 assert(ret == 1);
407 }
408
409 if (args.usecs)
410 usleep(args.usecs);
411
412 if (args.close_fds)
413 for (i = 0; i < nr_socks; i++)
414 close(fds[i]);
415
416 for (i = 0; i < nr; i++) {
417 if (io_uring_peek_cqe(&m_io_uring, &cqe))
418 break;
419 if (cqe->res != -ECANCELED) {
420 fprintf(stderr, "Expected cqe to be cancelled %d\n", cqe->res);
421 ret = 1;
422 goto out;
423 }
424 io_uring_cqe_seen(&m_io_uring, cqe);
425 }
426 ret = 0;
427 out:
428 rlim.rlim_cur = cur_lim;
429 if (setrlimit(RLIMIT_NPROC, &rlim) < 0) {
430 perror("setrlimit");
431 return 1;
432 }
433
434 free(fds);
435 io_uring_queue_exit(&m_io_uring);
436 return ret;
437 }
438
test_accept_cancel(unsigned usecs,unsigned int nr,bool multishot)439 static int test_accept_cancel(unsigned usecs, unsigned int nr, bool multishot)
440 {
441 struct io_uring m_io_uring;
442 struct io_uring_cqe *cqe;
443 struct io_uring_sqe *sqe;
444 int fd, i, ret;
445
446 if (multishot && no_accept_multi)
447 return 0;
448
449 ret = io_uring_queue_init(32, &m_io_uring, 0);
450 assert(ret >= 0);
451
452 fd = start_accept_listen(NULL, 0, 0);
453
454 for (i = 1; i <= nr; i++) {
455 sqe = io_uring_get_sqe(&m_io_uring);
456 if (!multishot)
457 io_uring_prep_accept(sqe, fd, NULL, NULL, 0);
458 else
459 io_uring_prep_multishot_accept(sqe, fd, NULL, NULL, 0);
460 sqe->user_data = i;
461 ret = io_uring_submit(&m_io_uring);
462 assert(ret == 1);
463 }
464
465 if (usecs)
466 usleep(usecs);
467
468 for (i = 1; i <= nr; i++) {
469 sqe = io_uring_get_sqe(&m_io_uring);
470 io_uring_prep_cancel64(sqe, i, 0);
471 sqe->user_data = nr + i;
472 ret = io_uring_submit(&m_io_uring);
473 assert(ret == 1);
474 }
475 for (i = 0; i < nr * 2; i++) {
476 ret = io_uring_wait_cqe(&m_io_uring, &cqe);
477 assert(!ret);
478 /*
479 * Two cases here:
480 *
481 * 1) We cancel the accept4() before it got started, we should
482 * get '0' for the cancel request and '-ECANCELED' for the
483 * accept request.
484 * 2) We cancel the accept4() after it's already running, we
485 * should get '-EALREADY' for the cancel request and
486 * '-EINTR' for the accept request.
487 */
488 if (cqe->user_data == 0) {
489 fprintf(stderr, "unexpected 0 user data\n");
490 goto err;
491 } else if (cqe->user_data <= nr) {
492 if (cqe->res != -EINTR && cqe->res != -ECANCELED) {
493 fprintf(stderr, "Cancelled accept got %d\n", cqe->res);
494 goto err;
495 }
496 } else if (cqe->user_data <= nr * 2) {
497 if (cqe->res != -EALREADY && cqe->res != 0) {
498 fprintf(stderr, "Cancel got %d\n", cqe->res);
499 goto err;
500 }
501 }
502 io_uring_cqe_seen(&m_io_uring, cqe);
503 }
504
505 io_uring_queue_exit(&m_io_uring);
506 close(fd);
507 return 0;
508 err:
509 io_uring_queue_exit(&m_io_uring);
510 close(fd);
511 return 1;
512 }
513
test_accept(int count,bool before)514 static int test_accept(int count, bool before)
515 {
516 struct io_uring m_io_uring;
517 int ret;
518 struct accept_test_args args = {
519 .queue_accept_before_connect = before,
520 .extra_loops = count - 1
521 };
522
523 ret = io_uring_queue_init(32, &m_io_uring, 0);
524 assert(ret >= 0);
525 ret = test(&m_io_uring, args);
526 io_uring_queue_exit(&m_io_uring);
527 return ret;
528 }
529
test_multishot_accept(int count,bool before)530 static int test_multishot_accept(int count, bool before)
531 {
532 struct io_uring m_io_uring;
533 int ret;
534 struct accept_test_args args = {
535 .queue_accept_before_connect = before,
536 .multishot = true,
537 .extra_loops = count - 1
538 };
539
540 if (no_accept_multi)
541 return 0;
542
543 ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0);
544 assert(ret >= 0);
545 ret = test(&m_io_uring, args);
546 io_uring_queue_exit(&m_io_uring);
547 return ret;
548 }
549
test_accept_multishot_wrong_arg()550 static int test_accept_multishot_wrong_arg()
551 {
552 struct io_uring m_io_uring;
553 struct io_uring_cqe *cqe;
554 struct io_uring_sqe *sqe;
555 int fd, ret;
556
557 ret = io_uring_queue_init(4, &m_io_uring, 0);
558 assert(ret >= 0);
559
560 fd = start_accept_listen(NULL, 0, 0);
561
562 sqe = io_uring_get_sqe(&m_io_uring);
563 io_uring_prep_multishot_accept_direct(sqe, fd, NULL, NULL, 0);
564 sqe->file_index = 1;
565 ret = io_uring_submit(&m_io_uring);
566 assert(ret == 1);
567
568 ret = io_uring_wait_cqe(&m_io_uring, &cqe);
569 assert(!ret);
570 if (cqe->res != -EINVAL) {
571 fprintf(stderr, "file index should be IORING_FILE_INDEX_ALLOC \
572 if its accept in multishot direct mode\n");
573 goto err;
574 }
575 io_uring_cqe_seen(&m_io_uring, cqe);
576
577 io_uring_queue_exit(&m_io_uring);
578 close(fd);
579 return 0;
580 err:
581 io_uring_queue_exit(&m_io_uring);
582 close(fd);
583 return 1;
584 }
585
586
test_accept_nonblock(bool queue_before_connect,int count)587 static int test_accept_nonblock(bool queue_before_connect, int count)
588 {
589 struct io_uring m_io_uring;
590 int ret;
591 struct accept_test_args args = {
592 .nonblock = true,
593 .queue_accept_before_connect = queue_before_connect,
594 .extra_loops = count - 1
595 };
596
597 ret = io_uring_queue_init(32, &m_io_uring, 0);
598 assert(ret >= 0);
599 ret = test(&m_io_uring, args);
600 io_uring_queue_exit(&m_io_uring);
601 return ret;
602 }
603
test_accept_fixed(void)604 static int test_accept_fixed(void)
605 {
606 struct io_uring m_io_uring;
607 int ret, fd = -1;
608 struct accept_test_args args = {
609 .fixed = true
610 };
611
612 ret = io_uring_queue_init(32, &m_io_uring, 0);
613 assert(ret >= 0);
614 ret = io_uring_register_files(&m_io_uring, &fd, 1);
615 assert(ret == 0);
616 ret = test(&m_io_uring, args);
617 io_uring_queue_exit(&m_io_uring);
618 return ret;
619 }
620
test_multishot_fixed_accept(void)621 static int test_multishot_fixed_accept(void)
622 {
623 struct io_uring m_io_uring;
624 int ret, fd[MAX_FDS];
625 struct accept_test_args args = {
626 .fixed = true,
627 .multishot = true
628 };
629
630 if (no_accept_multi)
631 return 0;
632
633 memset(fd, -1, sizeof(fd));
634 ret = io_uring_queue_init(MAX_FDS + 10, &m_io_uring, 0);
635 assert(ret >= 0);
636 ret = io_uring_register_files(&m_io_uring, fd, MAX_FDS);
637 assert(ret == 0);
638 ret = test(&m_io_uring, args);
639 io_uring_queue_exit(&m_io_uring);
640 return ret;
641 }
642
test_accept_sqpoll(void)643 static int test_accept_sqpoll(void)
644 {
645 struct io_uring m_io_uring;
646 struct io_uring_params p = { };
647 int ret;
648 struct accept_test_args args = { };
649
650 p.flags = IORING_SETUP_SQPOLL;
651 ret = t_create_ring_params(32, &m_io_uring, &p);
652 if (ret == T_SETUP_SKIP)
653 return 0;
654 else if (ret < 0)
655 return ret;
656
657 args.accept_should_error = 1;
658 if (p.features & IORING_FEAT_SQPOLL_NONFIXED)
659 args.accept_should_error = 0;
660
661 ret = test(&m_io_uring, args);
662 io_uring_queue_exit(&m_io_uring);
663 return ret;
664 }
665
main(int argc,char * argv[])666 int main(int argc, char *argv[])
667 {
668 int ret;
669
670 if (argc > 1)
671 return 0;
672 ret = test_accept(1, false);
673 if (ret) {
674 fprintf(stderr, "test_accept failed\n");
675 return ret;
676 }
677 if (no_accept)
678 return 0;
679
680 ret = test_accept(2, false);
681 if (ret) {
682 fprintf(stderr, "test_accept(2) failed\n");
683 return ret;
684 }
685
686 ret = test_accept(2, true);
687 if (ret) {
688 fprintf(stderr, "test_accept(2, true) failed\n");
689 return ret;
690 }
691
692 ret = test_accept_nonblock(false, 1);
693 if (ret) {
694 fprintf(stderr, "test_accept_nonblock failed\n");
695 return ret;
696 }
697
698 ret = test_accept_nonblock(true, 1);
699 if (ret) {
700 fprintf(stderr, "test_accept_nonblock(before, 1) failed\n");
701 return ret;
702 }
703
704 ret = test_accept_nonblock(true, 3);
705 if (ret) {
706 fprintf(stderr, "test_accept_nonblock(before,3) failed\n");
707 return ret;
708 }
709
710 ret = test_accept_fixed();
711 if (ret) {
712 fprintf(stderr, "test_accept_fixed failed\n");
713 return ret;
714 }
715
716 ret = test_multishot_fixed_accept();
717 if (ret) {
718 fprintf(stderr, "test_multishot_fixed_accept failed\n");
719 return ret;
720 }
721
722 ret = test_accept_multishot_wrong_arg();
723 if (ret) {
724 fprintf(stderr, "test_accept_multishot_wrong_arg failed\n");
725 return ret;
726 }
727
728 ret = test_accept_sqpoll();
729 if (ret) {
730 fprintf(stderr, "test_accept_sqpoll failed\n");
731 return ret;
732 }
733
734 ret = test_accept_cancel(0, 1, false);
735 if (ret) {
736 fprintf(stderr, "test_accept_cancel nodelay failed\n");
737 return ret;
738 }
739
740 ret = test_accept_cancel(10000, 1, false);
741 if (ret) {
742 fprintf(stderr, "test_accept_cancel delay failed\n");
743 return ret;
744 }
745
746 ret = test_accept_cancel(0, 4, false);
747 if (ret) {
748 fprintf(stderr, "test_accept_cancel nodelay failed\n");
749 return ret;
750 }
751
752 ret = test_accept_cancel(10000, 4, false);
753 if (ret) {
754 fprintf(stderr, "test_accept_cancel delay failed\n");
755 return ret;
756 }
757
758 ret = test_accept_cancel(0, 1, true);
759 if (ret) {
760 fprintf(stderr, "test_accept_cancel multishot nodelay failed\n");
761 return ret;
762 }
763
764 ret = test_accept_cancel(10000, 1, true);
765 if (ret) {
766 fprintf(stderr, "test_accept_cancel multishot delay failed\n");
767 return ret;
768 }
769
770 ret = test_accept_cancel(0, 4, true);
771 if (ret) {
772 fprintf(stderr, "test_accept_cancel multishot nodelay failed\n");
773 return ret;
774 }
775
776 ret = test_accept_cancel(10000, 4, true);
777 if (ret) {
778 fprintf(stderr, "test_accept_cancel multishot delay failed\n");
779 return ret;
780 }
781
782 ret = test_multishot_accept(1, false);
783 if (ret) {
784 fprintf(stderr, "test_multishot_accept(1, false) failed\n");
785 return ret;
786 }
787
788 ret = test_multishot_accept(1, true);
789 if (ret) {
790 fprintf(stderr, "test_multishot_accept(1, true) failed\n");
791 return ret;
792 }
793
794 ret = test_accept_many((struct test_accept_many_args) {});
795 if (ret) {
796 fprintf(stderr, "test_accept_many failed\n");
797 return ret;
798 }
799
800 ret = test_accept_many((struct test_accept_many_args) {
801 .usecs = 100000 });
802 if (ret) {
803 fprintf(stderr, "test_accept_many(sleep) failed\n");
804 return ret;
805 }
806
807 ret = test_accept_many((struct test_accept_many_args) {
808 .nonblock = true });
809 if (ret) {
810 fprintf(stderr, "test_accept_many(nonblock) failed\n");
811 return ret;
812 }
813
814 ret = test_accept_many((struct test_accept_many_args) {
815 .nonblock = true,
816 .single_sock = true,
817 .close_fds = true });
818 if (ret) {
819 fprintf(stderr, "test_accept_many(nonblock,close) failed\n");
820 return ret;
821 }
822
823 ret = test_accept_pending_on_exit();
824 if (ret) {
825 fprintf(stderr, "test_accept_pending_on_exit failed\n");
826 return ret;
827 }
828 return 0;
829 }
830