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