Module: wine Branch: master Commit: 7961e00e7429a4cd950a493ab9ff72448808d588 URL: https://gitlab.winehq.org/wine/wine/-/commit/7961e00e7429a4cd950a493ab9ff724...
Author: Zebediah Figura zfigura@codeweavers.com Date: Fri Jul 15 18:44:06 2022 -0500
server: Properly implement AFD_POLL_RESET.
---
dlls/ws2_32/tests/afd.c | 17 ++++++++--------- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c index eb525c78c54..21e7a50aef3 100644 --- a/dlls/ws2_32/tests/afd.c +++ b/dlls/ws2_32/tests/afd.c @@ -162,8 +162,7 @@ static void check_poll_(int line, SOCKET s, HANDLE event, int mask, int expect, ok_(__FILE__, line)(out_params.count == 1, "got count %u\n", out_params.count); ok_(__FILE__, line)(out_params.sockets[0].socket == s, "got socket %#Ix\n", out_params.sockets[0].socket); todo_wine_if (todo) ok_(__FILE__, line)(out_params.sockets[0].flags == expect, "got flags %#x\n", out_params.sockets[0].flags); - todo_wine_if (expect & AFD_POLL_RESET) - ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status); + ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status); }
static void test_poll(void) @@ -1407,10 +1406,10 @@ static void test_poll_reset(void) ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information); ok(out_params->count == 1, "got count %u\n", out_params->count); ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket); - todo_wine ok(out_params->sockets[0].flags == AFD_POLL_RESET, "got flags %#x\n", out_params->sockets[0].flags); - todo_wine ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status); + ok(out_params->sockets[0].flags == AFD_POLL_RESET, "got flags %#x\n", out_params->sockets[0].flags); + ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status);
- check_poll_todo(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_RESET); + check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_RESET);
closesocket(client); CloseHandle(event); @@ -2042,9 +2041,9 @@ static void test_get_events_reset(void) ret = NtDeviceIoControlFile((HANDLE)client, NULL, NULL, NULL, &io, IOCTL_AFD_GET_EVENTS, NULL, 0, ¶ms, sizeof(params)); ok(!ret, "got %#x\n", ret); - todo_wine ok(params.flags == (AFD_POLL_RESET | AFD_POLL_CONNECT | AFD_POLL_WRITE), "got flags %#x\n", params.flags); + ok(params.flags == (AFD_POLL_RESET | AFD_POLL_CONNECT | AFD_POLL_WRITE), "got flags %#x\n", params.flags); for (i = 0; i < ARRAY_SIZE(params.status); ++i) - todo_wine_if (i == AFD_POLL_BIT_HUP) ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
closesocket(client);
@@ -2060,9 +2059,9 @@ static void test_get_events_reset(void) ret = NtDeviceIoControlFile((HANDLE)server, NULL, NULL, NULL, &io, IOCTL_AFD_GET_EVENTS, NULL, 0, ¶ms, sizeof(params)); ok(!ret, "got %#x\n", ret); - todo_wine ok(params.flags == (AFD_POLL_RESET | AFD_POLL_WRITE), "got flags %#x\n", params.flags); + ok(params.flags == (AFD_POLL_RESET | AFD_POLL_WRITE), "got flags %#x\n", params.flags); for (i = 0; i < ARRAY_SIZE(params.status); ++i) - todo_wine_if (i == AFD_POLL_BIT_HUP) ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
closesocket(server);
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 576fe1cee6a..3e6faaffa4c 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -12861,7 +12861,7 @@ static void test_tcp_reset(void) len = sizeof(error); ret = getsockopt(client, SOL_SOCKET, SO_ERROR, (char *)&error, &len); ok(!ret, "got error %u\n", WSAGetLastError()); - todo_wine ok(!error, "got error %u\n", error); + ok(!error, "got error %u\n", error);
wsabuf.buf = buffer; wsabuf.len = sizeof(buffer); diff --git a/server/sock.c b/server/sock.c index 53553ab8ee7..7d7e470be28 100644 --- a/server/sock.c +++ b/server/sock.c @@ -232,6 +232,7 @@ struct sock unsigned int aborted : 1; /* did we get a POLLERR or irregular POLLHUP? */ unsigned int nonblocking : 1; /* is the socket nonblocking? */ unsigned int bound : 1; /* is the socket bound? */ + unsigned int reset : 1; /* did we get a TCP reset? */ };
static void sock_dump( struct object *obj, int verbose ); @@ -667,7 +668,12 @@ static inline int sock_error( struct sock *sock )
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: - if (error) + if (error == ECONNRESET || error == EPIPE) + { + sock->reset = 1; + error = 0; + } + else if (error) sock->errors[AFD_POLL_BIT_HUP] = error; else error = sock->errors[AFD_POLL_BIT_HUP]; @@ -897,6 +903,8 @@ static int get_poll_flags( struct sock *sock, int event ) flags |= AFD_POLL_HUP; if (event & POLLERR) flags |= AFD_POLL_CONNECT_ERR; + if (sock->reset) + flags |= AFD_POLL_RESET;
return flags; } @@ -1081,6 +1089,15 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) async_terminate( sock->connect_req->async, status ); }
+ if (sock->reset) + { + async_wake_up( &sock->read_q, STATUS_CONNECTION_RESET ); + async_wake_up( &sock->write_q, STATUS_CONNECTION_RESET ); + + if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING) + async_terminate( sock->accept_recv_req->async, STATUS_CONNECTION_RESET ); + } + return event; }
@@ -1116,6 +1133,9 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: + if (sock->reset) + post_socket_event( sock, AFD_POLL_BIT_RESET ); + if (event & POLLIN) post_socket_event( sock, AFD_POLL_BIT_READ );
@@ -1171,6 +1191,9 @@ static void sock_poll_event( struct fd *fd, int event )
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: + if (sock->reset) + event &= ~(POLLIN | POLLERR | POLLHUP); + if (sock->type == WS_SOCK_STREAM && (event & POLLIN)) { char dummy; @@ -1189,7 +1212,11 @@ static void sock_poll_event( struct fd *fd, int event ) event &= ~POLLIN; /* EAGAIN can happen if an async recv() falls between the server's poll() call and the invocation of this routine */ - if ( errno != EAGAIN ) + if (errno == ECONNRESET || errno == EPIPE) + { + sock->reset = 1; + } + else if (errno != EAGAIN) { error = errno; event |= POLLERR; @@ -1312,7 +1339,7 @@ static int sock_get_poll_events( struct fd *fd ) return -1; }
- if (sock->aborted) + if (sock->aborted || sock->reset) return -1;
if (sock->accept_recv_req) @@ -1517,6 +1544,7 @@ static struct sock *create_socket(void) sock->aborted = 0; sock->nonblocking = 0; sock->bound = 0; + sock->reset = 0; sock->rcvbuf = 0; sock->sndbuf = 0; sock->rcvtimeo = 0;