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