Mike Kaplinskiy : server: Always treat POLLHUP as a hangup, just special case checking TCP sockets.
Alexandre Julliard
julliard at winehq.org
Fri May 14 11:17:28 CDT 2010
Module: wine
Branch: master
Commit: d03fe9d4ecc98218516d263a0eeccb4928404658
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d03fe9d4ecc98218516d263a0eeccb4928404658
Author: Mike Kaplinskiy <mike.kaplinskiy at gmail.com>
Date: Thu May 13 16:41:58 2010 -0400
server: Always treat POLLHUP as a hangup, just special case checking TCP sockets.
---
server/sock.c | 37 ++++++++++++++++---------------------
1 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/server/sock.c b/server/sock.c
index a893863..75a9d00 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -329,6 +329,10 @@ static void sock_poll_event( struct fd *fd, int event )
assert( sock->obj.ops == &sock_ops );
if (debug_level)
fprintf(stderr, "socket %p select event: %x\n", sock, event);
+
+ /* we may change event later, remove from loop here */
+ if (event & (POLLERR|POLLHUP)) set_fd_events( sock->fd, -1 );
+
if (sock->state & FD_CONNECT)
{
/* connecting */
@@ -382,28 +386,25 @@ static void sock_poll_event( struct fd *fd, int event )
* has been closed, so we need to check for it explicitly here */
nr = recv( get_unix_fd( fd ), &dummy, 1, MSG_PEEK );
if ( nr == 0 )
+ {
hangup_seen = 1;
+ event &= ~POLLIN;
+ }
else if ( nr < 0 )
{
+ 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 )
- event &= ~POLLIN;
- else
+ if ( errno != EAGAIN )
{
if ( debug_level )
fprintf( stderr, "recv error on socket %p: %d\n", sock, errno );
- event = POLLERR;
+ event |= POLLERR;
}
}
-
- }
- else if ( sock_shutdown_type == SOCK_SHUTDOWN_POLLHUP && (event & POLLHUP) )
- {
- hangup_seen = 1;
}
- if ( event & POLLIN && !hangup_seen )
+ if ( event & POLLIN )
{
sock->pmask |= FD_READ;
sock->hmask |= FD_READ;
@@ -429,9 +430,7 @@ static void sock_poll_event( struct fd *fd, int event )
fprintf(stderr, "socket %p got OOB data\n", sock);
}
- /* According to WS2 specs, FD_CLOSE is only delivered when there is
- no more data to be read (i.e. hangup_seen = 1) */
- if ( hangup_seen && (sock->state & (FD_READ|FD_WRITE) ))
+ if ( (hangup_seen || event & (POLLHUP|POLLERR)) && (sock->state & (FD_READ|FD_WRITE)) )
{
sock->errors[FD_CLOSE_BIT] = sock_error( fd );
if ( (event & POLLERR) || ( sock_shutdown_type == SOCK_SHUTDOWN_EOF && (event & POLLHUP) ))
@@ -444,16 +443,10 @@ static void sock_poll_event( struct fd *fd, int event )
fprintf(stderr, "socket %p aborted by error %d, event: %x - removing from select loop\n",
sock, sock->errors[FD_CLOSE_BIT], event);
}
- }
- if ( event & (POLLERR|POLLHUP) )
- {
- if ( debug_level )
- fprintf( stderr, "removing socket %p from select loop\n", sock );
- set_fd_events( sock->fd, -1 );
+ if (hangup_seen)
+ event |= POLLHUP;
}
- else
- sock_reselect( sock );
/* wake up anyone waiting for whatever just happened */
if ( sock->pmask & sock->mask || sock->flags & WSA_FLAG_OVERLAPPED ) sock_wake_up( sock, event );
@@ -461,6 +454,8 @@ static void sock_poll_event( struct fd *fd, int event )
/* if anyone is stupid enough to wait on the socket object itself,
* maybe we should wake them up too, just in case? */
wake_up( &sock->obj, 0 );
+
+ sock_reselect( sock );
}
static void sock_dump( struct object *obj, int verbose )
More information about the wine-cvs
mailing list