xref: /xnu-12377.41.6/tests/accept_race.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1 #include <pthread.h>
2 #include <stdlib.h>
3 #include <arpa/inet.h>
4 #include <netinet/in.h>
5 #include <stdio.h>
6 #include <sys/socket.h>
7 #include <sys/types.h>
8 #include <sys/uio.h>
9 #include <unistd.h>
10 #include <darwintest.h>
11 
12 #include "net_test_lib.h"
13 
14 #define BASE_PORT 2020
15 
16 static int port = BASE_PORT;
17 static bool server_ready = false;
18 
19 static void
client(void)20 client(void)
21 {
22 	int i = 0;
23 	while (i < 9000) {
24 		int sock = socket(PF_INET, SOCK_STREAM, 0);
25 		T_QUIET; T_ASSERT_POSIX_SUCCESS(sock, "socket");
26 		struct sockaddr_in raddr;
27 		raddr.sin_family = AF_INET;
28 		raddr.sin_port = htons(port);
29 		raddr.sin_addr.s_addr = inet_addr("127.0.0.1");
30 		int res = connect(sock, (struct sockaddr *)&raddr, sizeof(raddr));
31 		if (res < 0 && (errno == EADDRNOTAVAIL || errno == ECONNREFUSED)) {
32 			close(sock);
33 			return;
34 		} else if (res < 0 && errno == ECONNREFUSED) {
35 		} else {
36 			T_QUIET; T_ASSERT_POSIX_SUCCESS(res, "connect");
37 		}
38 		close(sock);
39 		i++;
40 	}
41 }
42 
43 static void *
server(void * arg __unused)44 server(void *arg __unused)
45 {
46 	int sock = socket(PF_INET, SOCK_STREAM, 0);
47 	T_ASSERT_POSIX_SUCCESS(sock, "socket");
48 
49 	struct sockaddr_in laddr;
50 	laddr.sin_family = AF_INET;
51 	laddr.sin_port = htons(port);
52 	laddr.sin_addr.s_addr = 0;
53 	int res = bind(sock, (struct sockaddr *)&laddr, sizeof(laddr));
54 	if (res == -1 && errno == EADDRNOTAVAIL) {
55 		port = BASE_PORT;
56 		port += arc4random_uniform(512);
57 		res = bind(sock, (struct sockaddr *)&laddr, sizeof(laddr));
58 	}
59 	T_ASSERT_POSIX_SUCCESS(res, "bind");
60 	T_ASSERT_POSIX_SUCCESS(listen(sock, 10), "listen");
61 	server_ready = true;
62 	while (1) {
63 		struct sockaddr_in sin;
64 		socklen_t slen = sizeof(sin);
65 		int c = accept(sock, (struct sockaddr *)&sin, &slen);
66 		T_QUIET; T_ASSERT_POSIX_SUCCESS(c, "accept");
67 		char buf[1];
68 		T_QUIET; T_ASSERT_POSIX_SUCCESS(read(c, buf, 1), "read");
69 		close(c);
70 	}
71 	return NULL;
72 }
73 
74 T_DECL(accept_race,
75     "Exercises a race condition between socantrcvmore() and accept()",
76     T_META_CHECK_LEAKS(false), T_META_TAG_VM_NOT_PREFERRED)
77 {
78 	// Pick a random port
79 	port += arc4random_uniform(1024);
80 
81 	pthread_t server_th;
82 	if (pthread_create(&server_th, 0, server, NULL)) {
83 		T_FAIL("pthread_create failed");
84 	}
85 	while (!server_ready) {
86 		sleep(1);
87 	}
88 	client();
89 
90 	force_zone_gc();
91 }
92