* fhandler_socket.cc (fhandler_socket::evaluate_events): Handle the
FD_CLOSE event specially when called from accept. Explain why. (fhandler_socket::shutdown): Fake success on not-connected socket and trigger socket event if the read side of a socket is affected. Explain why. * poll.cc (poll): Check for saw_shutdown_read on sockets to generate POLLHUP as well.
This commit is contained in:
parent
7c8126eb3e
commit
0077cd1016
|
@ -1,3 +1,13 @@
|
|||
2011-04-18 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler_socket.cc (fhandler_socket::evaluate_events): Handle the
|
||||
FD_CLOSE event specially when called from accept. Explain why.
|
||||
(fhandler_socket::shutdown): Fake success on not-connected socket and
|
||||
trigger socket event if the read side of a socket is affected. Explain
|
||||
why.
|
||||
* poll.cc (poll): Check for saw_shutdown_read on sockets to generate
|
||||
POLLHUP as well.
|
||||
|
||||
2011-04-18 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* Fix various copyrights.
|
||||
|
|
|
@ -596,6 +596,15 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
|
|||
wsock_events->events &= ~FD_CONNECT;
|
||||
wsock_events->connect_errorcode = 0;
|
||||
}
|
||||
/* This test makes the accept function behave as on Linux when
|
||||
accept is called on a socket for which shutdown for the read side
|
||||
has been called. The second half of this code is in the shutdown
|
||||
method. See there for more info. */
|
||||
if ((event_mask & FD_ACCEPT) && (events & FD_CLOSE))
|
||||
{
|
||||
WSASetLastError (WSAEINVAL);
|
||||
ret = SOCKET_ERROR;
|
||||
}
|
||||
if (erase)
|
||||
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
|
||||
}
|
||||
|
@ -1659,22 +1668,37 @@ fhandler_socket::shutdown (int how)
|
|||
{
|
||||
int res = ::shutdown (get_socket (), how);
|
||||
|
||||
if (res)
|
||||
/* Linux allows to call shutdown for any socket, even if it's not connected.
|
||||
This also disables to call accept on this socket, if shutdown has been
|
||||
called with the SHUT_RD or SHUT_RDWR parameter. In contrast, Winsock
|
||||
only allows to call shutdown on a connected socket. The accept function
|
||||
is in no way affected. So, what we do here is to fake success, and to
|
||||
change the event settings so that an FD_CLOSE event is triggered for the
|
||||
calling Cygwin function. The evaluate_events method handles the call
|
||||
from accept specially to generate a Linux-compatible behaviour. */
|
||||
if (res && WSAGetLastError () != WSAENOTCONN)
|
||||
set_winsock_errno ();
|
||||
else
|
||||
switch (how)
|
||||
{
|
||||
case SHUT_RD:
|
||||
saw_shutdown_read (true);
|
||||
break;
|
||||
case SHUT_WR:
|
||||
saw_shutdown_write (true);
|
||||
break;
|
||||
case SHUT_RDWR:
|
||||
saw_shutdown_read (true);
|
||||
saw_shutdown_write (true);
|
||||
break;
|
||||
}
|
||||
{
|
||||
res = 0;
|
||||
switch (how)
|
||||
{
|
||||
case SHUT_RD:
|
||||
saw_shutdown_read (true);
|
||||
wsock_events->events |= FD_CLOSE;
|
||||
SetEvent (wsock_evt);
|
||||
break;
|
||||
case SHUT_WR:
|
||||
saw_shutdown_write (true);
|
||||
break;
|
||||
case SHUT_RDWR:
|
||||
saw_shutdown_read (true);
|
||||
saw_shutdown_write (true);
|
||||
wsock_events->events |= FD_CLOSE;
|
||||
SetEvent (wsock_evt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* poll.cc. Implements poll(2) via usage of select(2) call.
|
||||
|
||||
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
Red Hat, Inc.
|
||||
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||
2011 Red Hat, Inc.
|
||||
|
||||
This file is part of Cygwin.
|
||||
|
||||
|
@ -84,12 +84,16 @@ poll (struct pollfd *fds, nfds_t nfds, int timeout)
|
|||
{
|
||||
if (fds[i].fd >= 0)
|
||||
{
|
||||
if (cygheap->fdtab.not_open (fds[i].fd))
|
||||
fhandler_socket *sock;
|
||||
|
||||
/* Check if the descriptor has been closed, or if shutdown for the
|
||||
read side has been called on a socket. */
|
||||
if (cygheap->fdtab.not_open (fds[i].fd)
|
||||
|| ((sock = cygheap->fdtab[fds[i].fd]->is_socket ())
|
||||
&& sock->saw_shutdown_read ()))
|
||||
fds[i].revents = POLLHUP;
|
||||
else
|
||||
{
|
||||
fhandler_socket *sock;
|
||||
|
||||
if (FD_ISSET(fds[i].fd, read_fds))
|
||||
/* This should be sufficient for sockets, too. Using
|
||||
MSG_PEEK, as before, can be considered dangerous at
|
||||
|
|
Loading…
Reference in New Issue