xref: /xnu-8792.61.2/tests/accept_race.c (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
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 static int port = 2020;
13 static bool server_ready = false;
14 
15 static void
client(void)16 client(void)
17 {
18 	int i = 0;
19 	while (i < 9000) {
20 		int sock = socket(PF_INET, SOCK_STREAM, 0);
21 		T_QUIET; T_ASSERT_POSIX_SUCCESS(sock, "socket");
22 		struct sockaddr_in raddr;
23 		raddr.sin_family = AF_INET;
24 		raddr.sin_port = htons(port);
25 		raddr.sin_addr.s_addr = inet_addr("127.0.0.1");
26 		int res = connect(sock, (struct sockaddr *)&raddr, sizeof(raddr));
27 		if (res < 0 && (errno == EADDRNOTAVAIL || errno == ECONNREFUSED)) {
28 			close(sock);
29 			return;
30 		} else if (res < 0 && errno == ECONNREFUSED) {
31 		} else {
32 			T_QUIET; T_ASSERT_POSIX_SUCCESS(res, "connect");
33 		}
34 		close(sock);
35 		i++;
36 	}
37 }
38 
39 static void *
server(void * arg __unused)40 server(void *arg __unused)
41 {
42 	int sock = socket(PF_INET, SOCK_STREAM, 0);
43 	T_ASSERT_POSIX_SUCCESS(sock, "socket");
44 
45 	struct sockaddr_in laddr;
46 	laddr.sin_family = AF_INET;
47 	laddr.sin_port = htons(port);
48 	laddr.sin_addr.s_addr = 0;
49 	T_ASSERT_POSIX_SUCCESS(bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)), "bind");
50 	T_ASSERT_POSIX_SUCCESS(listen(sock, 10), "listen");
51 	server_ready = true;
52 	while (1) {
53 		struct sockaddr_in sin;
54 		socklen_t slen = sizeof(sin);
55 		int c = accept(sock, (struct sockaddr *)&sin, &slen);
56 		T_QUIET; T_ASSERT_POSIX_SUCCESS(c, "accept");
57 		char buf[1];
58 		T_QUIET; T_ASSERT_POSIX_SUCCESS(read(c, buf, 1), "read");
59 		close(c);
60 	}
61 	return NULL;
62 }
63 
64 T_DECL(accept_race, "Exercises a race condition between socantrcvmore() and accept()", T_META_CHECK_LEAKS(false))
65 {
66 	// Pick a random port
67 	port += arc4random_uniform(1024);
68 
69 	pthread_t server_th;
70 	if (pthread_create(&server_th, 0, server, NULL)) {
71 		T_FAIL("pthread_create failed");
72 	}
73 	while (!server_ready) {
74 		sleep(1);
75 	}
76 	client();
77 }
78