diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index d205c4754..a1f575ab4 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2005-04-18 Corinna Vinschen <corinna@vinschen.de> + + * 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. + 2005-04-18 Christopher Faylor <cgf@timesys.com> * include/cygwin/version.h: Bump DLL minor number to 16. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index a7fcb9086..7611378bd 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -50,7 +50,8 @@ enum conn_state { unconnected = 0, connect_pending = 1, - connected = 2 + connected = 2, + connect_failed = 3 }; enum line_edit_status diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index aa412081e..7c7e2daf8 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -706,7 +706,7 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) err = WSAGetLastError (); /* Special handling for connect to return the correct error code when called on a non-blocking socket. */ - if (is_nonblocking () || connect_state () == connect_pending) + if (is_nonblocking ()) { if (err == WSAEWOULDBLOCK || err == WSAEALREADY) in_progress = true; @@ -736,6 +736,8 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) if (err == WSAEINPROGRESS || err == WSAEALREADY) connect_state (connect_pending); + else if (err) + connect_state (connect_failed); else connect_state (connected); 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; + } } } } diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 1c469cf63..2daa88a5f 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -352,7 +352,7 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds, { UNIX_FD_SET (me->fd, writefds); if ((sock = me->fh->is_socket ())) - sock->connect_state (connected); + sock->connect_state (connect_failed); } if (me->except_selected) UNIX_FD_SET (me->fd, exceptfds); @@ -915,7 +915,7 @@ fhandler_dev_null::select_except (select_record *s) } s->h = get_handle (); s->except_selected = true; - s->except_ready = true; + s->except_ready = false; return s; } @@ -1271,11 +1271,11 @@ peek_socket (select_record *me, bool) set_winsock_errno (); return 0; } - if (WINSOCK_FD_ISSET (h, &ws_readfds) || (me->read_selected && me->read_ready)) + if (WINSOCK_FD_ISSET (h, &ws_readfds)) me->read_ready = true; - if (WINSOCK_FD_ISSET (h, &ws_writefds) || (me->write_selected && me->write_ready)) + if (WINSOCK_FD_ISSET (h, &ws_writefds)) me->write_ready = true; - if (WINSOCK_FD_ISSET (h, &ws_exceptfds) || ((me->except_selected || me->except_on_write) && me->except_ready)) + if (WINSOCK_FD_ISSET (h, &ws_exceptfds)) me->except_ready = true; } return me->read_ready || me->write_ready || me->except_ready; @@ -1460,7 +1460,7 @@ fhandler_socket::select_write (select_record *s) s->peek = peek_socket; s->write_ready = saw_shutdown_write () || connect_state () == unconnected; s->write_selected = true; - if (connect_state () == connect_pending) + if (connect_state () != unconnected) { s->except_ready = saw_shutdown_write () || saw_shutdown_read (); s->except_on_write = true; @@ -1559,7 +1559,7 @@ fhandler_windows::select_except (select_record *s) s->peek = peek_windows; s->h = get_handle (); s->except_selected = true; - s->except_ready = true; + s->except_ready = false; s->windows_handle = true; return s; }