Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/sock.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 8b0b56f4070..bd65cfc68c3 100644 --- a/server/sock.c +++ b/server/sock.c @@ -112,8 +112,19 @@ struct sock struct fd *fd; /* socket file descriptor */ unsigned int state; /* status bits */ unsigned int mask; /* event mask */ - unsigned int pending_events; /* pending FD_* events which have not yet been reported to the application */ - unsigned int hmask; /* held (blocked) events */ + /* pending FD_* events which have not yet been reported to the application */ + unsigned int pending_events; + /* FD_* events which have already been reported and should not be selected + * for again until reset by a relevant call. + * + * For example, if FD_READ is set here and not in pending_events, it has + * already been reported and consumed, and we should not report it again, + * even if POLLIN is signaled, until it is reset by e.g recv(). + * + * If an event has been signaled and not consumed yet, it will be set in + * both pending_events and reported_events (as we should only ever report + * any event once until it is reset.) */ + unsigned int reported_events; unsigned int flags; /* socket flags */ int polling; /* is socket being polled? */ unsigned short proto; /* socket protocol */ @@ -617,7 +628,7 @@ static void post_socket_event( struct sock *sock, unsigned int event_bit, unsign unsigned int event = (1 << event_bit);
sock->pending_events |= event; - sock->hmask |= event; + sock->reported_events |= event; sock->errors[event_bit] = error; }
@@ -743,15 +754,15 @@ static void sock_dump( struct object *obj, int verbose ) { struct sock *sock = (struct sock *)obj; assert( obj->ops == &sock_ops ); - fprintf( stderr, "Socket fd=%p, state=%x, mask=%x, pending=%x, held=%x\n", + fprintf( stderr, "Socket fd=%p, state=%x, mask=%x, pending=%x, reported=%x\n", sock->fd, sock->state, - sock->mask, sock->pending_events, sock->hmask ); + sock->mask, sock->pending_events, sock->reported_events ); }
static int sock_get_poll_events( struct fd *fd ) { struct sock *sock = get_fd_user( fd ); - unsigned int mask = sock->mask & ~sock->hmask; + unsigned int mask = sock->mask & ~sock->reported_events; unsigned int smask = sock->state & mask; int ev = 0;
@@ -773,7 +784,7 @@ static int sock_get_poll_events( struct fd *fd ) ev |= POLLIN | POLLPRI; /* We use POLLIN with 0 bytes recv() as FD_CLOSE indication for stream sockets. */ else if (sock->type == WS_SOCK_STREAM && (sock->state & FD_READ) && (mask & FD_CLOSE) && - !(sock->hmask & FD_READ)) + !(sock->reported_events & FD_READ)) ev |= POLLIN;
if (async_queued( &sock->write_q )) @@ -892,8 +903,8 @@ static struct sock *create_socket(void) sock->fd = NULL; sock->state = 0; sock->mask = 0; - sock->hmask = 0; sock->pending_events = 0; + sock->reported_events = 0; sock->polling = 0; sock->flags = 0; sock->proto = 0; @@ -1144,7 +1155,7 @@ static struct sock *accept_socket( struct sock *sock ) } clear_error(); sock->pending_events &= ~FD_ACCEPT; - sock->hmask &= ~FD_ACCEPT; + sock->reported_events &= ~FD_ACCEPT; sock_reselect( sock ); return acceptsock; } @@ -1179,8 +1190,8 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock ) }
acceptsock->state |= FD_WINE_CONNECTED|FD_READ|FD_WRITE; - acceptsock->hmask = 0; acceptsock->pending_events = 0; + acceptsock->reported_events = 0; acceptsock->polling = 0; acceptsock->proto = sock->proto; acceptsock->type = sock->type; @@ -1194,7 +1205,7 @@ static int accept_into_socket( struct sock *sock, struct sock *acceptsock )
clear_error(); sock->pending_events &= ~FD_ACCEPT; - sock->hmask &= ~FD_ACCEPT; + sock->reported_events &= ~FD_ACCEPT; sock_reselect( sock );
return TRUE; @@ -1769,7 +1780,7 @@ DECL_HANDLER(set_socket_event) if (get_unix_fd( sock->fd ) == -1) return; old_event = sock->event; sock->mask = req->mask; - sock->hmask &= ~req->mask; /* re-enable held events */ + sock->reported_events &= ~req->mask; /* re-enable held events */ sock->event = NULL; sock->window = req->window; sock->message = req->msg; @@ -1837,7 +1848,7 @@ DECL_HANDLER(enable_socket_event) /* for event-based notification, windows erases stale events */ sock->pending_events &= ~req->mask;
- sock->hmask &= ~req->mask; + sock->reported_events &= ~req->mask; sock->state |= req->sstate; sock->state &= ~req->cstate; if (sock->type != WS_SOCK_STREAM) sock->state &= ~STREAM_FLAG_MASK;