This fixes a `todo_wine` in ws2_32's socket tests.
-- v5: server: Defer listens on addresses currently bound first by another socket.
From: Ally Sommers dropbear.sh@gmail.com
--- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 31dff1a11c7..1278dfb0fa3 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -2298,7 +2298,7 @@ static void test_reuseaddr(void) rc = listen(s1, 1); ok(!rc, "got error %d.\n", WSAGetLastError()); rc = listen(s2, 1); - todo_wine ok(!rc, "got error %d.\n", WSAGetLastError()); + ok(!rc, "got error %d.\n", WSAGetLastError()); rc = connect(s3, tests[i].addr_loopback, tests[i].addrlen); ok(!rc, "got error %d.\n", WSAGetLastError());
diff --git a/server/sock.c b/server/sock.c index ac55a5448f7..4150f36bd31 100644 --- a/server/sock.c +++ b/server/sock.c @@ -193,6 +193,7 @@ struct bound_addr union unix_sockaddr addr; int match_any_addr; int reuse_count; + struct sock *sock; };
#define MAX_ICMP_HISTORY_LENGTH 8 @@ -264,6 +265,9 @@ struct sock unsigned int reset : 1; /* did we get a TCP reset? */ unsigned int reuseaddr : 1; /* winsock SO_REUSEADDR option value */ unsigned int exclusiveaddruse : 1; /* winsock SO_EXCLUSIVEADDRUSE option value */ + unsigned int listen_queued : 1; /* listen() while bound to an in-use address? */ + int listen_backlog; /* stored argument for deferred listen() */ + struct list bind_list; /* ordered list of sockets bound to the same address */ };
static int is_tcp_socket( struct sock *sock ) @@ -397,10 +401,12 @@ static struct bound_addr *register_bound_address( struct sock *sock, const union return NULL; } ++bound_addr->reuse_count; + list_add_tail(&bound_addr->sock->bind_list, &sock->bind_list); } else { bound_addr->reuse_count = sock->reuseaddr ? 1 : -1; + bound_addr->sock = sock; } return bound_addr; } @@ -1663,7 +1669,29 @@ static int sock_close_handle( struct object *obj, struct process *process, obj_h
if (signaled) complete_async_poll( poll_req, STATUS_SUCCESS ); } + + list_remove(&sock->bind_list); + + close( get_unix_fd( sock->fd ) ); + + if (sock->bound_addr[0] && sock->bound_addr[0]->sock == sock) + { + struct sock *new_sock; + struct list *next_list_elem = list_next( &sock->bind_list, &sock->bind_list ); + if (!next_list_elem) + goto no_next_socket_or_deferred_listen; + + new_sock = LIST_ENTRY( next_list_elem, struct sock, bind_list ); + sock->bound_addr[0]->sock = new_sock; + if (sock->bound_addr[1]) + sock->bound_addr[1]->sock = new_sock; + + if (new_sock->listen_queued) + if (listen( get_unix_fd( new_sock->fd ), new_sock->listen_backlog ) == -1 && debug_level) + fprintf( stderr, "FIXME: deferred listen threw errno %d (%s)\n", errno, strerror(errno) ); + } } +no_next_socket_or_deferred_listen: return async_close_obj_handle( obj, process, handle ); }
@@ -1740,6 +1768,8 @@ static struct sock *create_socket(void) sock->rcvtimeo = 0; sock->sndtimeo = 0; sock->icmp_fixup_data_len = 0; + sock->listen_queued = 0; + sock->listen_backlog = 0; sock->bound_addr[0] = sock->bound_addr[1] = NULL; init_async_queue( &sock->read_q ); init_async_queue( &sock->write_q ); @@ -1749,6 +1779,7 @@ static struct sock *create_socket(void) init_async_queue( &sock->poll_q ); memset( sock->errors, 0, sizeof(sock->errors) ); list_init( &sock->accept_list ); + list_init( &sock->bind_list ); return sock; }
@@ -2539,12 +2570,20 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return; }
+ if (sock->bound_addr[0] && sock->bound_addr[0]->sock != sock) + { + sock->listen_backlog = params->backlog; + sock->listen_queued = 1; + goto listen_skip_error; + } + if (listen( unix_fd, params->backlog ) < 0) { set_error( sock_get_ntstatus( errno ) ); return; }
+ listen_skip_error: sock->state = SOCK_LISTENING;
/* a listening socket can no longer be accepted into */
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=137565
Your paranoid android.
=== debian11 (32 bit report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit ar:MA report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit de report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit fr report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit he:IL report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit hi:IN report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit ja:JP report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11 (32 bit zh:CN report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11b (32 bit WoW report) ===
ws2_32: sock.c:9016: Test failed: GetOverlappedResult failed, error 6 sock.c:9021: Test failed: Failed to get data, -1, errno: 10057 sock.c:9022: Test failed: The wrong first client was accepted by acceptex: 0 != 1
=== debian11b (64 bit WoW report) ===
Report validation errors: ieframe:webbrowser timeout
=== debian11b (build log) ===
WineRunWineTest.pl:error: The task timed out