summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog9
-rw-r--r--winsup/cygwin/fhandler_socket.cc3
-rw-r--r--winsup/cygwin/include/sys/poll.h6
-rw-r--r--winsup/cygwin/poll.cc44
4 files changed, 25 insertions, 37 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 5e3f33762..e55394f79 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,14 @@
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
potential race condition.
(fhandler_socket::recv_internal): Fix MSG_PEEK bug on blocking sockets
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 6a1cdd1e0..0fecdaaac 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -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);
diff --git a/winsup/cygwin/include/sys/poll.h b/winsup/cygwin/include/sys/poll.h
index a5bd4bded..7fd1c6eb0 100644
--- a/winsup/cygwin/include/sys/poll.h
+++ b/winsup/cygwin/include/sys/poll.h
@@ -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
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index a7db49ef8..3be689c90 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -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 ())