Loading...
#include <pthread.h> #include <stdlib.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> #include <darwintest.h> #include "net_test_lib.h" T_GLOBAL_META( T_META_NAMESPACE("xnu.net"), T_META_RADAR_COMPONENT_NAME("xnu"), T_META_RADAR_COMPONENT_VERSION("networking"), T_META_OWNER("rpaulo") ); #define BASE_PORT 2020 static int port = BASE_PORT; static bool server_ready = false; static void client(void) { int i = 0; while (i < 9000) { int sock = socket(PF_INET, SOCK_STREAM, 0); T_QUIET; T_ASSERT_POSIX_SUCCESS(sock, "socket"); struct sockaddr_in raddr; raddr.sin_family = AF_INET; raddr.sin_port = htons(port); raddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int res = connect(sock, (struct sockaddr *)&raddr, sizeof(raddr)); if (res < 0 && (errno == EADDRNOTAVAIL || errno == ECONNREFUSED)) { close(sock); return; } else if (res < 0 && errno == ECONNREFUSED) { } else { T_QUIET; T_ASSERT_POSIX_SUCCESS(res, "connect"); } close(sock); i++; } } static void * server(void *arg __unused) { int sock = socket(PF_INET, SOCK_STREAM, 0); T_ASSERT_POSIX_SUCCESS(sock, "socket"); struct sockaddr_in laddr; laddr.sin_family = AF_INET; laddr.sin_port = htons(port); laddr.sin_addr.s_addr = 0; int res = bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)); if (res == -1 && (errno == EADDRNOTAVAIL || errno == EADDRINUSE)) { port = BASE_PORT; port += arc4random_uniform(512); laddr.sin_port = htons(port); res = bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)); } T_ASSERT_POSIX_SUCCESS(res, "bind"); T_ASSERT_POSIX_SUCCESS(listen(sock, 10), "listen"); server_ready = true; while (1) { struct sockaddr_in sin; socklen_t slen = sizeof(sin); int c = accept(sock, (struct sockaddr *)&sin, &slen); T_QUIET; T_ASSERT_POSIX_SUCCESS(c, "accept"); char buf[1]; T_QUIET; T_ASSERT_POSIX_SUCCESS(read(c, buf, 1), "read"); close(c); } return NULL; } T_DECL(accept_race, "Exercises a race condition between socantrcvmore() and accept()", T_META_CHECK_LEAKS(false), T_META_ENABLED(!TARGET_OS_BRIDGE), T_META_TAG_VM_NOT_PREFERRED) { // Pick a random port port += arc4random_uniform(1024); pthread_t server_th; if (pthread_create(&server_th, 0, server, NULL)) { T_FAIL("pthread_create failed"); } while (!server_ready) { sleep(1); } client(); force_zone_gc(); } |