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