* fhandler_socket.cc (fhandler_socket::recv_internal): Fix a problem

with poll(2) after shutdown(SHUT_RD) has been called on the local side.
	* poll.cc (poll): Use POSIX type nfds_t for second parameter.  Drop
	special socket handling for POLLIN.  Add comment to explain why.
	* include/sys/poll.h: Declare nfds_t.  Use as type for second parameter
	in poll(2) declaration.
This commit is contained in:
Corinna Vinschen 2006-07-31 14:27:56 +00:00
parent 1f7dbb011a
commit b23bc8c33c
4 changed files with 25 additions and 37 deletions

View File

@ -1,3 +1,12 @@
2006-07-31 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::recv_internal): Fix a problem
with poll(2) after shutdown(SHUT_RD) has been called on the local side.
* poll.cc (poll): Use POSIX type nfds_t for second parameter. Drop
special socket handling for POLLIN. Add comment to explain why.
* include/sys/poll.h: Declare nfds_t. Use as type for second parameter
in poll(2) declaration.
2006-07-31 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::evaluate_events): Circumvent

View File

@ -1160,7 +1160,8 @@ fhandler_socket::recv_internal (WSABUF *wsabuf, DWORD wsacnt, DWORD flags,
/* Note: Don't call WSARecvFrom(MSG_PEEK) without actually having data
waiting in the buffers, otherwise the event handling gets messed up
for some reason. */
while (!(res = wait_for_events (evt_mask | FD_CLOSE)))
while (!(res = wait_for_events (evt_mask | FD_CLOSE))
|| saw_shutdown_read ())
{
res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &ret,
&flags, from, fromlen, NULL, NULL);

View File

@ -1,6 +1,6 @@
/* sys/poll.h
Copyright 2000, 2001 Red Hat, Inc.
Copyright 2000, 2001, 2006 Red Hat, Inc.
This file is part of Cygwin.
@ -36,7 +36,9 @@ struct pollfd {
short revents;
};
extern int poll __P ((struct pollfd *fds, unsigned int nfds, int timeout));
typedef unsigned int nfds_t;
extern int poll __P ((struct pollfd *fds, nfds_t nfds, int timeout));
__END_DECLS

View File

@ -27,7 +27,7 @@
#include "sigproc.h"
extern "C" int
poll (struct pollfd *fds, unsigned int nfds, int timeout)
poll (struct pollfd *fds, nfds_t nfds, int timeout)
{
int max_fd = 0;
fd_set *read_fds, *write_fds, *except_fds;
@ -90,39 +90,15 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
fhandler_socket *sock;
if (FD_ISSET(fds[i].fd, read_fds))
{
char peek[1];
sock = cygheap->fdtab[fds[i].fd]->is_socket ();
if (!sock)
fds[i].revents |= POLLIN;
else if (sock->listener ())
{
fds[i].revents |= POLLIN;
}
else
{
/* The following action can change errno. We have to
reset it to it's old value. */
int old_errno = get_errno ();
switch (sock->recvfrom (peek, sizeof (peek), MSG_PEEK,
NULL, NULL))
{
case -1:
fds[i].revents |= POLLERR;
break;
case 0: /* Closed on the read side... */
/* ...or shutdown(SHUT_WR) on the write side.
We set revents to POLLHUP until 1.5.18, but
this is semantically borderline. */
fds[i].revents |= POLLIN;
break;
default:
fds[i].revents |= POLLIN;
break;
}
set_errno (old_errno);
}
}
/* This should be sufficient for sockets, too. Using
MSG_PEEK, as before, can be considered dangerous at
best. Quote from W. Richard Stevens: "The presence
of an error can be considered either normal data or
an error (POLLERR). In either case, a subsequent read
will return -1 with errno set to the appropriate value."
So it looks like there's actually no good reason to
return POLLERR. */
fds[i].revents |= POLLIN;
/* Handle failed connect. */
if (FD_ISSET(fds[i].fd, write_fds)
&& (sock = cygheap->fdtab[fds[i].fd]->is_socket ())