Module: wine Branch: master Commit: 361435f6095f8c759979600b06ed28785e7b3aec URL: https://source.winehq.org/git/wine.git/?a=commit;h=361435f6095f8c759979600b0...
Author: Zebediah Figura zfigura@codeweavers.com Date: Mon Jul 26 11:53:44 2021 -0500
server: Remove the socket from the polling loop if both it and the peer have SHUT_WR.
Based on a patch by Torge Matthies.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51319 Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
server/sock.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/server/sock.c b/server/sock.c index 85ea019ad92..2d2aa733565 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1161,6 +1161,20 @@ static int sock_get_poll_events( struct fd *fd )
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: + if (sock->hangup && sock->wr_shutdown && !sock->wr_shutdown_pending) + { + /* Linux returns POLLHUP if a socket is both SHUT_RD and SHUT_WR, or + * if both the socket and its peer are SHUT_WR. + * + * We don't use SHUT_RD, so we can only encounter this in the latter + * case. In that case there can't be any pending read requests (they + * would have already been completed with a length of zero), the + * above condition ensures that we don't have any pending write + * requests, and nothing that can change about the socket state that + * would complete a pending poll request. */ + return -1; + } + if (sock->accept_recv_req) { ev |= POLLIN; @@ -1267,7 +1281,10 @@ static void sock_reselect_async( struct fd *fd, struct async_queue *queue ) struct sock *sock = get_fd_user( fd );
if (sock->wr_shutdown_pending && list_empty( &sock->write_q.queue )) + { shutdown( get_unix_fd( sock->fd ), SHUT_WR ); + sock->wr_shutdown_pending = 0; + }
/* Don't reselect the ifchange queue; we always ask for POLLIN. * Don't reselect an uninitialized socket; we can't call set_fd_events() on