Zebediah Figura : server: Use separate fields to track socket shutdown state.
Alexandre Julliard
julliard at winehq.org
Fri Jun 11 15:31:29 CDT 2021
Module: wine
Branch: master
Commit: 5eaba82a7719e1f059ef5636aee37c4e49f28626
URL: https://source.winehq.org/git/wine.git/?a=commit;h=5eaba82a7719e1f059ef5636aee37c4e49f28626
Author: Zebediah Figura <z.figura12 at gmail.com>
Date: Thu Jun 10 19:36:25 2021 -0500
server: Use separate fields to track socket shutdown state.
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
server/sock.c | 59 ++++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 21 deletions(-)
diff --git a/server/sock.c b/server/sock.c
index 7941ed856d3..4cd84637baf 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -172,6 +172,8 @@ struct sock
struct list accept_list; /* list of pending accept requests */
struct accept_req *accept_recv_req; /* pending accept-into request which will recv on this socket */
struct connect_req *connect_req; /* pending connection request */
+ unsigned int rd_shutdown : 1; /* is the read end shut down? */
+ unsigned int wr_shutdown : 1; /* is the write end shut down? */
unsigned int wr_shutdown_pending : 1; /* is a write shutdown pending? */
unsigned int nonblocking : 1; /* is the socket nonblocking? */
};
@@ -781,9 +783,9 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
int status = sock_get_ntstatus( error );
struct accept_req *req, *next;
- if (!(sock->state & FD_READ))
+ if (sock->rd_shutdown)
async_wake_up( &sock->read_q, status );
- if (!(sock->state & FD_WRITE))
+ if (sock->wr_shutdown)
async_wake_up( &sock->write_q, status );
LIST_FOR_EACH_ENTRY_SAFE( req, next, &sock->accept_list, struct accept_req, entry )
@@ -869,7 +871,7 @@ static void sock_poll_event( struct fd *fd, int event )
else if (event & POLLOUT)
{
/* we got connected */
- sock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+ sock->state |= FD_WINE_CONNECTED;
sock->state &= ~FD_CONNECT;
sock->connect_time = current_time;
}
@@ -911,12 +913,12 @@ static void sock_poll_event( struct fd *fd, int event )
}
}
- if ( (hangup_seen || event & (POLLHUP|POLLERR)) && (sock->state & (FD_READ|FD_WRITE)) )
+ if ((hangup_seen || event & (POLLHUP | POLLERR)) && (!sock->rd_shutdown || !sock->wr_shutdown))
{
error = error ? error : sock_error( fd );
if ( (event & POLLERR) || ( sock_shutdown_type == SOCK_SHUTDOWN_EOF && (event & POLLHUP) ))
- sock->state &= ~FD_WRITE;
- sock->state &= ~FD_READ;
+ sock->wr_shutdown = 1;
+ sock->rd_shutdown = 1;
if (debug_level)
fprintf(stderr, "socket %p aborted by error %d, event: %x\n", sock, error, event);
@@ -969,7 +971,6 @@ static int sock_get_poll_events( struct fd *fd )
{
struct sock *sock = get_fd_user( fd );
unsigned int mask = sock->mask & ~sock->reported_events;
- unsigned int smask = sock->state & mask;
struct poll_req *req;
int ev = 0;
@@ -996,7 +997,12 @@ static int sock_get_poll_events( struct fd *fd )
{
if (async_waiting( &sock->read_q )) ev |= POLLIN | POLLPRI;
}
- else if (smask & FD_READ || (sock->state & FD_WINE_LISTENING && mask & FD_ACCEPT))
+ else if (sock->state & FD_WINE_LISTENING)
+ {
+ if (mask & FD_ACCEPT)
+ ev |= POLLIN;
+ }
+ else if (!sock->rd_shutdown && (mask & FD_READ))
ev |= POLLIN | POLLPRI;
/* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */
else if (sock->type == WS_SOCK_STREAM && (mask & FD_CLOSE) && !(sock->reported_events & FD_READ))
@@ -1006,7 +1012,7 @@ static int sock_get_poll_events( struct fd *fd )
{
if (async_waiting( &sock->write_q )) ev |= POLLOUT;
}
- else if (smask & FD_WRITE)
+ else if (!sock->wr_shutdown && (mask & FD_WRITE))
ev |= POLLOUT;
LIST_FOR_EACH_ENTRY( req, &poll_list, struct poll_req, entry )
@@ -1039,18 +1045,30 @@ static void sock_queue_async( struct fd *fd, struct async *async, int type, int
switch (type)
{
case ASYNC_TYPE_READ:
+ if (sock->rd_shutdown)
+ {
+ set_error( STATUS_PIPE_DISCONNECTED );
+ return;
+ }
queue = &sock->read_q;
break;
+
case ASYNC_TYPE_WRITE:
+ if (sock->wr_shutdown)
+ {
+ set_error( STATUS_PIPE_DISCONNECTED );
+ return;
+ }
queue = &sock->write_q;
break;
+
default:
set_error( STATUS_INVALID_PARAMETER );
return;
}
- if ( ( !( sock->state & (FD_READ|FD_CONNECT|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ ) ||
- ( !( sock->state & (FD_WRITE|FD_CONNECT) ) && type == ASYNC_TYPE_WRITE ) )
+ if ( ( !( sock->state & (FD_CONNECT|FD_WINE_LISTENING) ) && type == ASYNC_TYPE_READ ) ||
+ ( !( sock->state & (FD_CONNECT) ) && type == ASYNC_TYPE_WRITE ) )
{
set_error( STATUS_PIPE_DISCONNECTED );
return;
@@ -1180,6 +1198,8 @@ static struct sock *create_socket(void)
sock->ifchange_obj = NULL;
sock->accept_recv_req = NULL;
sock->connect_req = NULL;
+ sock->rd_shutdown = 0;
+ sock->wr_shutdown = 0;
sock->wr_shutdown_pending = 0;
sock->nonblocking = 0;
init_async_queue( &sock->read_q );
@@ -1339,7 +1359,6 @@ static int init_socket( struct sock *sock, int family, int type, int protocol, u
}
#endif
- sock->state = (type != SOCK_STREAM) ? (FD_READ|FD_WRITE) : 0;
sock->flags = flags;
sock->proto = protocol;
sock->type = type;
@@ -1404,7 +1423,7 @@ static struct sock *accept_socket( struct sock *sock )
}
/* newly created socket gets the same properties of the listening socket */
- acceptsock->state = FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+ acceptsock->state = FD_WINE_CONNECTED;
acceptsock->nonblocking = sock->nonblocking;
acceptsock->mask = sock->mask;
acceptsock->proto = sock->proto;
@@ -1458,7 +1477,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
return FALSE;
}
- acceptsock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE;
+ acceptsock->state |= FD_WINE_CONNECTED;
acceptsock->pending_events = 0;
acceptsock->reported_events = 0;
acceptsock->proto = sock->proto;
@@ -1808,7 +1827,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
if (!ret)
{
- sock->state |= FD_WINE_CONNECTED | FD_READ | FD_WRITE;
+ sock->state |= FD_WINE_CONNECTED;
sock->state &= ~FD_CONNECT;
if (!send_len) return 1;
@@ -1866,11 +1885,11 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
if (how != SD_SEND)
{
- sock->state &= ~FD_READ;
+ sock->rd_shutdown = 1;
}
if (how != SD_RECEIVE)
{
- sock->state &= ~FD_WRITE;
+ sock->wr_shutdown = 1;
if (list_empty( &sock->write_q.queue ))
shutdown( unix_fd, SHUT_WR );
else
@@ -2462,8 +2481,7 @@ DECL_HANDLER(recv_socket)
status = STATUS_PENDING;
}
- /* are we shut down? */
- if (status == STATUS_PENDING && !(sock->state & FD_READ)) status = STATUS_PIPE_DISCONNECTED;
+ if (status == STATUS_PENDING && sock->rd_shutdown) status = STATUS_PIPE_DISCONNECTED;
sock->pending_events &= ~(req->oob ? FD_OOB : FD_READ);
sock->reported_events &= ~(req->oob ? FD_OOB : FD_READ);
@@ -2567,8 +2585,7 @@ DECL_HANDLER(send_socket)
status = STATUS_PENDING;
}
- /* are we shut down? */
- if (status == STATUS_PENDING && !(sock->state & FD_WRITE)) status = STATUS_PIPE_DISCONNECTED;
+ if (status == STATUS_PENDING && sock->wr_shutdown) status = STATUS_PIPE_DISCONNECTED;
if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async )))
{
More information about the wine-cvs
mailing list