diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c18b33f09..23aa6dc11 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,19 @@ +2006-07-27 Corinna Vinschen <corinna@vinschen.de> + + * fhandler_socket.cc: Revert misguided attempt to handle FD_CLOSE error + conditions in evaluate_events. + (search_wsa_event_slot): Move wrongly placed memset in + fhandler_socket::init_events here. + (fhandler_socket::init_events): Initially set FD_WRITE event for + connectionless sockets. + * poll.cc (poll): Don't add sockets always to except_fds since select + is now supposed to do it right. + * select.cc (set_bits): Set connection state correctly for failed + af_local_connect on local sockets. Remove socket special handling + for except_selected descriptors. + (peek_socket): Try to set the read/write/exception bits actually + correctly. + 2006-07-27 Brian Ford <Brian.Ford@FlightSafety.com> * fhandler_socket.cc (fhandler_socket::recvmsg): Remove unused tot diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 760dbc456..4a5177a02 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -386,7 +386,7 @@ struct wsa_event { LONG serial_number; long events; - int errorcode; + int connect_errorcode; pid_t owner; }; @@ -443,6 +443,7 @@ search_wsa_event_slot (LONG new_serial_number) return NULL; } } + memset (&wsa_events[slot], 0, sizeof (wsa_event)); wsa_events[slot].serial_number = new_serial_number; ReleaseMutex (wsa_slot_mtx); return wsa_events + slot; @@ -490,7 +491,9 @@ fhandler_socket::init_events () return false; } wsock_events = search_wsa_event_slot (new_serial_number); - memset (wsock_events, 0, sizeof *wsock_events); + /* sock type not yet set here. */ + if (pc.dev == FH_UDP || pc.dev == FH_DGRAM) + wsock_events->events = FD_WRITE; return true; } @@ -508,9 +511,7 @@ fhandler_socket::evaluate_events (const long event_mask, long &events, LOCK_EVENTS; wsock_events->events |= evts.lNetworkEvents; if (evts.lNetworkEvents & FD_CONNECT) - wsock_events->errorcode = evts.iErrorCode[FD_CONNECT_BIT]; - else if (evts.lNetworkEvents & FD_CLOSE) - wsock_events->errorcode = evts.iErrorCode[FD_CLOSE_BIT]; + wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT]; UNLOCK_EVENTS; if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner) kill (wsock_events->owner, SIGURG); @@ -520,22 +521,18 @@ fhandler_socket::evaluate_events (const long event_mask, long &events, LOCK_EVENTS; if ((events = (wsock_events->events & event_mask)) != 0) { - if (events & (FD_CONNECT | FD_CLOSE)) + if (events & FD_CONNECT) { int wsa_err = 0; - if ((wsa_err = wsock_events->errorcode) != 0) + if ((wsa_err = wsock_events->connect_errorcode) != 0) { WSASetLastError (wsa_err); ret = SOCKET_ERROR; } - if (events & FD_CONNECT) - { - if (!wsock_events->errorcode) - wsock_events->events |= FD_WRITE; - wsock_events->events &= ~FD_CONNECT; - } - if (!(events & FD_CLOSE)) - wsock_events->errorcode = 0; + else + wsock_events->events |= FD_WRITE; + wsock_events->events &= ~FD_CONNECT; + wsock_events->connect_errorcode = 0; } if (erase) wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE)); diff --git a/winsup/cygwin/poll.cc b/winsup/cygwin/poll.cc index 3ce46fab6..a7db49ef8 100644 --- a/winsup/cygwin/poll.cc +++ b/winsup/cygwin/poll.cc @@ -1,6 +1,6 @@ /* poll.cc. Implements poll(2) via usage of select(2) call. - Copyright 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. This file is part of Cygwin. @@ -63,9 +63,7 @@ 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); - /* On sockets, except_fds is needed to catch failed connects. */ - if ((fds[i].events & POLLPRI) - || cygheap->fdtab[fds[i].fd]->is_socket ()) + if (fds[i].events & POLLPRI) FD_SET(fds[i].fd, except_fds); } else if (fds[i].fd >= 0) @@ -127,7 +125,6 @@ poll (struct pollfd *fds, unsigned int nfds, int timeout) } /* 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); diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index abfe9e5a3..e5b50d375 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -364,22 +364,20 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds, { /* Special AF_LOCAL handling. */ if (!me->read_ready && sock->connect_state () == connect_pending - && sock->af_local_connect () && me->read_selected) - UNIX_FD_SET (me->fd, readfds); - sock->connect_state (connected); + && sock->af_local_connect ()) + { + if (me->read_selected) + UNIX_FD_SET (me->fd, readfds); + sock->connect_state (connect_failed); + } + else + sock->connect_state (connected); } ready++; } - if ((me->except_selected || me->except_on_write) && me->except_ready) + if (me->except_selected && me->except_ready) { - if (me->except_on_write) /* Only on sockets */ - { - UNIX_FD_SET (me->fd, writefds); - if ((sock = me->fh->is_socket ())) - sock->connect_state (connect_failed); - } - if (me->except_selected) - UNIX_FD_SET (me->fd, exceptfds); + UNIX_FD_SET (me->fd, exceptfds); ready++; } select_printf ("ready %d", ready); @@ -1264,23 +1262,21 @@ peek_socket (select_record *me, bool) { fhandler_socket *fh = (fhandler_socket *) me->fh; long events; - long evt_mask = (FD_CLOSE - | (me->read_selected ? (FD_READ | FD_ACCEPT) : 0) - | (me->write_selected ? (FD_WRITE | FD_CONNECT) : 0) - | (me->except_selected ? (FD_OOB | FD_CONNECT) : 0)); + /* Don't play with the settings again, unless having taken a deep look into + Richard W. Stevens Network Programming book. Thank you. */ + long evt_mask = (me->read_selected ? (FD_READ | FD_ACCEPT | FD_CLOSE) : 0) + | (me->write_selected ? (FD_WRITE | FD_CONNECT | FD_CLOSE) : 0) + | (me->except_selected ? FD_OOB : 0); int ret = fh->evaluate_events (evt_mask, events, false); if (me->read_selected) - me->read_ready |= !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE)); + me->read_ready |= ret || !!(events & (FD_READ | FD_ACCEPT | FD_CLOSE)); if (me->write_selected) - { - if ((events & FD_CONNECT) && !ret) - me->write_ready = true; - else - me->write_ready |= !!(events & (FD_WRITE | FD_CLOSE)); - } + me->write_ready |= ret || !!(events & (FD_WRITE | FD_CONNECT | FD_CLOSE)); if (me->except_selected) - me->except_ready |= ret || !!(events & FD_OOB); + me->except_ready |= !!(events & FD_OOB); + select_printf ("read_ready: %d, write_ready: %d, except_ready: %d", + me->read_ready, me->write_ready, me->except_ready); return me->read_ready || me->write_ready || me->except_ready; }