Skip to content

Commit 8cecd90

Browse files
authored
Adjust state when starting an accept (#787)
Set the flags that an accept is in-progress regardless of whether it completes or not, resolving an assertion failure. This is not currently possible to test with Wasmtime, but with bytecodealliance/wasmtime#13158 and the test included here the assertion is hit reliably.
1 parent a16b32f commit 8cecd90

3 files changed

Lines changed: 88 additions & 1 deletion

File tree

libc-bottom-half/sources/tcp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,8 @@ static bool wasip3_tcp_accept_start(tcp_socket_state_listening_t *state) {
343343
!(state->flags & TCP_LISTENING_ACCEPT_READY)) {
344344
wasip3_waitable_status_t status = sockets_stream_own_tcp_socket_read(
345345
state->stream, &state->accept_result, 1);
346+
state->flags |= TCP_LISTENING_ACCEPTING;
346347
if (status == WASIP3_WAITABLE_STATUS_BLOCKED) {
347-
state->flags |= TCP_LISTENING_ACCEPTING;
348348
return true;
349349
}
350350
wasip3_tcp_accept_finish(state, status);

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ if (NOT (WASI STREQUAL "p1"))
416416
add_wasilibc_test(sockets-nonblocking.c NETWORK)
417417
add_wasilibc_test(sockets-nonblocking-udp-no-connection.c NETWORK)
418418
add_wasilibc_test(sockets-eof-delayed.c NETWORK)
419+
add_wasilibc_test(sockets-nonblocking-accept-multiple.c NETWORK)
419420

420421
# Define executables for server/client tests, and they're paired together in
421422
# various combinations below for various tests.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#include "test.h"
2+
#include <arpa/inet.h>
3+
#include <errno.h>
4+
#include <fcntl.h>
5+
#include <netdb.h>
6+
#include <netinet/in.h>
7+
#include <poll.h>
8+
#include <stdio.h>
9+
#include <stdlib.h>
10+
#include <string.h>
11+
#include <sys/socket.h>
12+
#include <unistd.h>
13+
14+
#define TEST(c) \
15+
do { \
16+
errno = 0; \
17+
if (!(c)) \
18+
t_error("%s failed (errno = %d)\n", #c, errno); \
19+
} while (0)
20+
21+
#define N 10
22+
23+
int main() {
24+
int listener_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
25+
26+
// Setup a listener bound to port 0 to have the OS assign us one.
27+
struct sockaddr_in server_address;
28+
socklen_t server_address_len = sizeof(server_address);
29+
server_address.sin_family = AF_INET;
30+
server_address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
31+
server_address.sin_port = 0;
32+
TEST(bind(listener_fd, (struct sockaddr *)&server_address,
33+
sizeof(server_address)) != -1);
34+
TEST(getsockname(listener_fd, (struct sockaddr *)&server_address,
35+
&server_address_len) != -1);
36+
TEST(listen(listener_fd, N) != -1);
37+
38+
struct pollfd clients[N];
39+
int remaining = N;
40+
41+
// Connect N clients, then wait for them all to reach the writable state
42+
// meaning that they're more-or-less
43+
// connected.
44+
for (int i = 0; i < N; i++) {
45+
int client_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
46+
TEST(client_fd != -1);
47+
int rc;
48+
TEST((rc = connect(client_fd, (struct sockaddr *)&server_address,
49+
server_address_len)) != -1 ||
50+
errno == EINPROGRESS);
51+
clients[i].fd = client_fd;
52+
if (rc == -1) {
53+
clients[i].events = POLLWRNORM;
54+
} else {
55+
remaining--;
56+
clients[i].events = 0;
57+
}
58+
}
59+
60+
while (remaining > 0) {
61+
TEST(poll(clients, N, -1) > 0);
62+
63+
for (int i = 0; i < N; i++) {
64+
if (clients[i].revents & POLLWRNORM) {
65+
clients[i].events = 0;
66+
remaining--;
67+
}
68+
}
69+
}
70+
71+
// Now accept everything quickly and close it all.
72+
for (int i = 0; i < N; i++) {
73+
struct pollfd listener;
74+
listener.fd = listener_fd;
75+
listener.events = POLLRDNORM;
76+
TEST(poll(&listener, 1, -1) == 1);
77+
int server_fd;
78+
TEST((server_fd = accept(listener_fd, NULL, NULL)) != -1);
79+
TEST(close(server_fd) != -1);
80+
}
81+
82+
for (int i = 0; i < N; i++)
83+
TEST(close(clients[i].fd) != -1);
84+
85+
return t_status;
86+
}

0 commit comments

Comments
 (0)