diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-28 23:31:07 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-28 23:31:07 +0100 |
| commit | 772873104658182a5b76f5c0eed76047c62c6651 (patch) | |
| tree | 431ba9c063fab10b4356cd8c7e63c9d2e957e2d9 /tests/t_socket.c | |
| parent | dd0ad26ea9824b75accced2b56328cbb222c4c6d (diff) | |
With more workers blockingly waiting on udp sockets, we need to keep track of all sockets to shut them down on exit
Diffstat (limited to 'tests/t_socket.c')
| -rw-r--r-- | tests/t_socket.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/tests/t_socket.c b/tests/t_socket.c index 8eef7fd..ede8ae0 100644 --- a/tests/t_socket.c +++ b/tests/t_socket.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <poll.h> | 10 | #include <poll.h> |
| 11 | #include <string.h> | 11 | #include <string.h> |
| 12 | #include <sys/socket.h> | 12 | #include <sys/socket.h> |
| 13 | #include <time.h> | ||
| 13 | #include <unistd.h> | 14 | #include <unistd.h> |
| 14 | 15 | ||
| 15 | /* Opentracker */ | 16 | /* Opentracker */ |
| @@ -144,6 +145,44 @@ static void case_udp_roundtrip(void) { | |||
| 144 | close(s); | 145 | close(s); |
| 145 | } | 146 | } |
| 146 | 147 | ||
| 148 | /* udp_workers_deinit relies on a worker parked in a read coming back. The | ||
| 149 | receive timeout is what guarantees that; shutting the socket down is what | ||
| 150 | makes it prompt where the platform allows it. Neither is uniform across the | ||
| 151 | systems opentracker runs on, so both are checked rather than assumed. */ | ||
| 152 | static void case_blocking_read_comes_back(void) { | ||
| 153 | char buf[32], ip[16], own_ip[16]; | ||
| 154 | uint16_t port = 0, own_port = 0; | ||
| 155 | time_t started; | ||
| 156 | int s; | ||
| 157 | |||
| 158 | test_case("a receive timeout does not delay a datagram that is already there"); | ||
| 159 | s = socket_udp_bind(ip_loopback, 0, SOCKET_EXCLUSIVE); | ||
| 160 | CHECK(s != -1); | ||
| 161 | CHECK_INT(socket_set_blocking(s, 1), 0); | ||
| 162 | CHECK_INT(socket_set_timeout(s, 1), 0); | ||
| 163 | bound_address(s, own_ip, &own_port); | ||
| 164 | CHECK_INT(socket_send(s, "opentracker", 11, own_ip, own_port), 11); | ||
| 165 | CHECK_INT(socket_recv(s, buf, sizeof(buf), ip, &port), 11); | ||
| 166 | |||
| 167 | test_case("and ends a read that would otherwise never return"); | ||
| 168 | started = time(NULL); | ||
| 169 | CHECK_INT(socket_recv(s, buf, sizeof(buf), ip, &port), -1); | ||
| 170 | CHECK(errno == EAGAIN || errno == EWOULDBLOCK); | ||
| 171 | CHECK(time(NULL) - started <= 3); | ||
| 172 | close(s); | ||
| 173 | |||
| 174 | test_case("shutting the socket down ends one too"); | ||
| 175 | s = socket_udp_bind(ip_loopback, 0, SOCKET_EXCLUSIVE); | ||
| 176 | CHECK(s != -1); | ||
| 177 | CHECK_INT(socket_set_blocking(s, 1), 0); | ||
| 178 | CHECK_INT(socket_set_timeout(s, 1), 0); | ||
| 179 | shutdown(s, SHUT_RD); | ||
| 180 | started = time(NULL); | ||
| 181 | CHECK(socket_recv(s, buf, sizeof(buf), ip, &port) <= 0); | ||
| 182 | CHECK(time(NULL) - started <= 3); | ||
| 183 | close(s); | ||
| 184 | } | ||
| 185 | |||
| 147 | /* An IPv4 peer must arrive in the v4 mapped form opentracker stores, however | 186 | /* An IPv4 peer must arrive in the v4 mapped form opentracker stores, however |
| 148 | the kernel chose to report it. Linux fills a v4 mapped sockaddr_in6 here | 187 | the kernel chose to report it. Linux fills a v4 mapped sockaddr_in6 here |
| 149 | and the BSDs fill a plain sockaddr_in, so this is the case that tells the | 188 | and the BSDs fill a plain sockaddr_in, so this is the case that tells the |
| @@ -293,6 +332,7 @@ void test_socket(void) { | |||
| 293 | case_sharing_is_opt_in(); | 332 | case_sharing_is_opt_in(); |
| 294 | #endif | 333 | #endif |
| 295 | case_udp_roundtrip(); | 334 | case_udp_roundtrip(); |
| 335 | case_blocking_read_comes_back(); | ||
| 296 | case_udp_v4mapped(); | 336 | case_udp_v4mapped(); |
| 297 | case_tcp_roundtrip(); | 337 | case_tcp_roundtrip(); |
| 298 | case_connect_refused(); | 338 | case_connect_refused(); |
