Zebediah Figura : server: Properly implement AFD_POLL_RESET.
Alexandre Julliard
julliard at winehq.org
Mon Jul 25 16:17:21 CDT 2022
Module: wine
Branch: master
Commit: 7961e00e7429a4cd950a493ab9ff72448808d588
URL: https://gitlab.winehq.org/wine/wine/-/commit/7961e00e7429a4cd950a493ab9ff72448808d588
Author: Zebediah Figura <zfigura at 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;
More information about the wine-cvs
mailing list