* 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>
|
2011-04-18 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* Fix various copyrights.
|
* Fix various copyrights.
|
||||||
|
|
|
@ -596,6 +596,15 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
|
||||||
wsock_events->events &= ~FD_CONNECT;
|
wsock_events->events &= ~FD_CONNECT;
|
||||||
wsock_events->connect_errorcode = 0;
|
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)
|
if (erase)
|
||||||
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
|
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
|
||||||
}
|
}
|
||||||
|
@ -1659,22 +1668,37 @@ fhandler_socket::shutdown (int how)
|
||||||
{
|
{
|
||||||
int res = ::shutdown (get_socket (), 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 ();
|
set_winsock_errno ();
|
||||||
else
|
else
|
||||||
switch (how)
|
{
|
||||||
{
|
res = 0;
|
||||||
case SHUT_RD:
|
switch (how)
|
||||||
saw_shutdown_read (true);
|
{
|
||||||
break;
|
case SHUT_RD:
|
||||||
case SHUT_WR:
|
saw_shutdown_read (true);
|
||||||
saw_shutdown_write (true);
|
wsock_events->events |= FD_CLOSE;
|
||||||
break;
|
SetEvent (wsock_evt);
|
||||||
case SHUT_RDWR:
|
break;
|
||||||
saw_shutdown_read (true);
|
case SHUT_WR:
|
||||||
saw_shutdown_write (true);
|
saw_shutdown_write (true);
|
||||||
break;
|
break;
|
||||||
}
|
case SHUT_RDWR:
|
||||||
|
saw_shutdown_read (true);
|
||||||
|
saw_shutdown_write (true);
|
||||||
|
wsock_events->events |= FD_CLOSE;
|
||||||
|
SetEvent (wsock_evt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* poll.cc. Implements poll(2) via usage of select(2) call.
|
/* poll.cc. Implements poll(2) via usage of select(2) call.
|
||||||
|
|
||||||
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
|
||||||
Red Hat, Inc.
|
2011 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
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 (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;
|
fds[i].revents = POLLHUP;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fhandler_socket *sock;
|
|
||||||
|
|
||||||
if (FD_ISSET(fds[i].fd, read_fds))
|
if (FD_ISSET(fds[i].fd, read_fds))
|
||||||
/* This should be sufficient for sockets, too. Using
|
/* This should be sufficient for sockets, too. Using
|
||||||
MSG_PEEK, as before, can be considered dangerous at
|
MSG_PEEK, as before, can be considered dangerous at
|
||||||
|
|
Loading…
Reference in New Issue