Cygwin: select: Fix FD_CLOSE handling
An FD_CLOSE event sets a socket descriptor ready for writing. This is incorrect if the FD_CLOSE is a result of shutdown(SHUT_RD). Only set the socket descriptor ready for writing if the FD_CLOSE is indicating an connection abort or reset error condition. This requires to tweak fhandler_socket_wsock::evaluate_events. FD_CLOSE in conjunction with FD_ACCEPT/FD_CONNECT special cases a shutdown condition by setting an error code. This is correct for accept/connect, but not for select. In this case, make sure to return with an error code only if FD_CLOSE indicates a connection error. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
caa78917b6
commit
ef95c03522
|
@ -361,10 +361,19 @@ fhandler_socket_wsock::evaluate_events (const long event_mask, long &events,
|
||||||
wsock_events->events |= FD_WRITE;
|
wsock_events->events |= FD_WRITE;
|
||||||
wsock_events->connect_errorcode = 0;
|
wsock_events->connect_errorcode = 0;
|
||||||
}
|
}
|
||||||
/* This test makes accept/connect behave as on Linux when accept/connect
|
|
||||||
is called on a socket for which shutdown has been called. The second
|
|
||||||
half of this code is in the shutdown method. */
|
|
||||||
if (events & FD_CLOSE)
|
if (events & FD_CLOSE)
|
||||||
|
{
|
||||||
|
if (evts.iErrorCode[FD_CLOSE_BIT])
|
||||||
|
{
|
||||||
|
WSASetLastError (evts.iErrorCode[FD_CLOSE_BIT]);
|
||||||
|
ret = SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
/* This test makes accept/connect behave as on Linux when accept/
|
||||||
|
connect is called on a socket for which shutdown has been called.
|
||||||
|
The second half of this code is in the shutdown method. Note that
|
||||||
|
we only do this when called from accept/connect, not from select.
|
||||||
|
In this case erase == false, just as with read (MSG_PEEK). */
|
||||||
|
if (erase)
|
||||||
{
|
{
|
||||||
if ((event_mask & FD_ACCEPT) && saw_shutdown_read ())
|
if ((event_mask & FD_ACCEPT) && saw_shutdown_read ())
|
||||||
{
|
{
|
||||||
|
@ -377,6 +386,7 @@ fhandler_socket_wsock::evaluate_events (const long event_mask, long &events,
|
||||||
ret = SOCKET_ERROR;
|
ret = SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (erase)
|
if (erase)
|
||||||
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
|
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1709,7 +1709,8 @@ peek_socket (select_record *me, bool)
|
||||||
fhandler_socket_wsock *fh = (fhandler_socket_wsock *) me->fh;
|
fhandler_socket_wsock *fh = (fhandler_socket_wsock *) me->fh;
|
||||||
long events;
|
long events;
|
||||||
/* Don't play with the settings again, unless having taken a deep look into
|
/* Don't play with the settings again, unless having taken a deep look into
|
||||||
Richard W. Stevens Network Programming book. Thank you. */
|
Richard W. Stevens Network Programming book and how these flags are
|
||||||
|
defined in Winsock. Thank you. */
|
||||||
long evt_mask = (me->read_selected ? (FD_READ | FD_ACCEPT | FD_CLOSE) : 0)
|
long evt_mask = (me->read_selected ? (FD_READ | FD_ACCEPT | FD_CLOSE) : 0)
|
||||||
| (me->write_selected ? (FD_WRITE | FD_CONNECT | FD_CLOSE) : 0)
|
| (me->write_selected ? (FD_WRITE | FD_CONNECT | FD_CLOSE) : 0)
|
||||||
| (me->except_selected ? FD_OOB : 0);
|
| (me->except_selected ? FD_OOB : 0);
|
||||||
|
@ -1717,7 +1718,9 @@ peek_socket (select_record *me, bool)
|
||||||
if (me->read_selected)
|
if (me->read_selected)
|
||||||
me->read_ready |= ret || !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE));
|
me->read_ready |= ret || !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE));
|
||||||
if (me->write_selected)
|
if (me->write_selected)
|
||||||
me->write_ready |= ret || !!(events & (FD_WRITE | FD_CONNECT | FD_CLOSE));
|
/* Don't check for FD_CLOSE here. Only an error case (ret == -1)
|
||||||
|
will set ready for writing. */
|
||||||
|
me->write_ready |= ret || !!(events & (FD_WRITE | FD_CONNECT));
|
||||||
if (me->except_selected)
|
if (me->except_selected)
|
||||||
me->except_ready |= !!(events & FD_OOB);
|
me->except_ready |= !!(events & FD_OOB);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue