summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/poll.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-04-18 18:56:52 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-04-18 18:56:52 +0000
commit04843bf4a05314c57cf2036917a0e52d95b79ade (patch)
treebbca4a0ea3133a0d6fbee71d9ff7e6057e2ee8d0 /winsup/cygwin/poll.cc
parent2180b9627dbb4ef05b6205b678b36376511967e6 (diff)
downloadcygnal-04843bf4a05314c57cf2036917a0e52d95b79ade.tar.gz
cygnal-04843bf4a05314c57cf2036917a0e52d95b79ade.tar.bz2
cygnal-04843bf4a05314c57cf2036917a0e52d95b79ade.zip
* fhandler.h (enum conn_state): Add connect_failed state.
* fhandler_socket.cc (fhandler_socket::connect): Set connect_state to connect_failed when connect failed. * poll.cc (poll): Change errno to EINVAL if allocating memory fails, according to SUSv3. Add socket descriptors always to except_fds. Test for failed connect and set revents flags appropriately. * select.cc (set_bits): Set connect_state to connect_failed when select indicates failed nonblocking connect. (fhandler_dev_null::select_except): Set except_ready to false so that /dev/null is not always in except state. (peek_socket): Fix bogus conditional. (fhandler_socket::select_write): Treat all connect_states except unconnected equivalent to return consistent results. (fhandler_windows::select_except): Set except_ready to false so that /dev/windows is not always in except state.
Diffstat (limited to 'winsup/cygwin/poll.cc')
-rw-r--r--winsup/cygwin/poll.cc28
1 files changed, 20 insertions, 8 deletions
diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc
index c6a98f422..50f675372 100644
--- a/winsup/cygwin/poll.cc
+++ b/winsup/cygwin/poll.cc
@@ -45,7 +45,7 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
if (!read_fds || !write_fds || !except_fds)
{
- set_errno (ENOMEM);
+ set_errno (EINVAL); /* According to SUSv3. */
return -1;
}
@@ -63,7 +63,9 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
FD_SET(fds[i].fd, read_fds);
if (fds[i].events & POLLOUT)
FD_SET(fds[i].fd, write_fds);
- if (fds[i].events & POLLPRI)
+ /* On sockets, except_fds is needed to catch failed connects. */
+ if ((fds[i].events & POLLPRI)
+ || cygheap->fdtab[fds[i].fd]->is_socket ())
FD_SET(fds[i].fd, except_fds);
}
else if (fds[i].fd >= 0)
@@ -87,11 +89,12 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
fds[i].revents = POLLHUP;
else
{
+ fhandler_socket *sock;
+
if (FD_ISSET(fds[i].fd, read_fds))
{
char peek[1];
- fhandler_socket *sock =
- cygheap->fdtab[fds[i].fd]->is_socket ();
+ sock = cygheap->fdtab[fds[i].fd]->is_socket ();
if (!sock)
fds[i].revents |= POLLIN;
else
@@ -125,10 +128,19 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout)
set_errno (old_errno);
}
}
- if (FD_ISSET(fds[i].fd, write_fds))
- fds[i].revents |= POLLOUT;
- if (FD_ISSET(fds[i].fd, except_fds))
- fds[i].revents |= POLLPRI;
+ /* Handle failed connect. */
+ if (FD_ISSET(fds[i].fd, write_fds)
+ && FD_ISSET(fds[i].fd, except_fds)
+ && (sock = cygheap->fdtab[fds[i].fd]->is_socket ())
+ && sock->connect_state () == connect_failed)
+ fds[i].revents |= (POLLIN | POLLERR);
+ else
+ {
+ if (FD_ISSET(fds[i].fd, write_fds))
+ fds[i].revents |= POLLOUT;
+ if (FD_ISSET(fds[i].fd, except_fds))
+ fds[i].revents |= POLLPRI;
+ }
}
}
}