diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 15f24ae98..849e5a623 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,25 @@ +2002-07-05 Corinna Vinschen + + * fhandler.h (UNCONNECTED): New define. + (CONNECT_PENDING): Ditto. + (CONNECTED): Ditto. + (class fhandler_socket): Add member `had_connect_or_listen'. + Add member functions `is_unconnected', `is_connect_pending' and + `is_connected'. + * fhandler_socket.cc (fhandler_socket::connect): Set member + `had_connect_or_listen' according to return code of WinSock + call. + (fhandler_socket::listen): Ditto. + * net.cc (cygwin_getsockopt): Modify SO_ERROR return value in + case of socket with pending connect(). + * select.cc (peek_socket): Only add socket to matching fd_set + if it's not "ready". Call WINSOCK_SELECT only if at least one + socket is in one of the fd_sets. + (start_thread_socket): Only add socket to matching fd_set + if it's not "ready". + (fhandler_socket::select_write): Set write_ready to true also + if socket isn't connected or listening. + 2002-07-04 Corinna Vinschen * fhandler_socket.cc (fhandler_socket::set_sun_path): Don't free diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 5727d24ab..980957a67 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -101,6 +101,10 @@ enum both flags are set. */ #define O_NONBLOCK_MASK (O_NONBLOCK | OLD_O_NDELAY) +#define UNCONNECTED 0 +#define CONNECT_PENDING 1 +#define CONNECTED 2 + extern const char *windows_device_names[]; extern struct __cygwin_perfile *perfile_table; #define __fmode (*(user_data->fmode_ptr)) @@ -367,6 +371,7 @@ class fhandler_socket: public fhandler_base HANDLE secret_event; struct _WSAPROTOCOL_INFOA *prot_info_ptr; char *sun_path; + int had_connect_or_listen; public: fhandler_socket (); @@ -380,6 +385,10 @@ class fhandler_socket: public fhandler_base void set_shutdown_read () {FHSETF (SHUTRD);} void set_shutdown_write () {FHSETF (SHUTWR);} + bool is_unconnected () {return had_connect_or_listen == UNCONNECTED;} + bool is_connect_pending () {return had_connect_or_listen == CONNECT_PENDING;} + bool is_connected () {return had_connect_or_listen == CONNECTED;} + int bind (const struct sockaddr *name, int namelen); int connect (const struct sockaddr *name, int namelen); int listen (int backlog); diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 7970e4b63..e95655510 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -455,6 +455,10 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) } } + if (!res) + had_connect_or_listen = CONNECTED; + else if (WSAGetLastError () == WSAEINPROGRESS) + had_connect_or_listen = CONNECT_PENDING; return res; } @@ -464,6 +468,8 @@ fhandler_socket::listen (int backlog) int res = ::listen (get_socket (), backlog); if (res) set_winsock_errno (); + else + had_connect_or_listen = CONNECTED; return res; } diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 870bf7865..1445ae683 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -712,6 +712,8 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen) if (optname == SO_ERROR) { int *e = (int *) optval; + if (!*e && fh->is_connect_pending ()) + *e = WSAEINPROGRESS; *e = find_winsock_errno (*e); } diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index b50ffb1f2..46f0c6963 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1180,39 +1180,44 @@ peek_socket (select_record *me, bool) set_handle_or_return_if_not_open (h, me); select_printf ("considering handle %p", h); - if (me->read_selected) + if (me->read_selected && !me->read_ready) { select_printf ("adding read fd_set %s, fd %d", me->fh->get_name (), me->fd); WINSOCK_FD_SET (h, &ws_readfds); } - if (me->write_selected) + if (me->write_selected && !me->write_ready) { select_printf ("adding write fd_set %s, fd %d", me->fh->get_name (), me->fd); WINSOCK_FD_SET (h, &ws_writefds); } - if (me->except_selected) + if (me->except_selected && !me->except_ready) { select_printf ("adding except fd_set %s, fd %d", me->fh->get_name (), me->fd); WINSOCK_FD_SET (h, &ws_exceptfds); } - int r = WINSOCK_SELECT (0, &ws_readfds, &ws_writefds, &ws_exceptfds, &tv); - select_printf ("WINSOCK_SELECT returned %d", r); - if (r == -1) + int r; + if ((me->read_selected && !me->read_ready) + || (me->write_selected && !me->write_ready) + || (me->except_selected && !me->except_ready)) { - select_printf ("error %d", WSAGetLastError ()); - set_winsock_errno (); - return 0; + r = WINSOCK_SELECT (0, &ws_readfds, &ws_writefds, &ws_exceptfds, &tv); + select_printf ("WINSOCK_SELECT returned %d", r); + if (r == -1) + { + select_printf ("error %d", WSAGetLastError ()); + set_winsock_errno (); + return 0; + } + if (WINSOCK_FD_ISSET (h, &ws_readfds) || (me->read_selected && me->read_ready)) + me->read_ready = true; + if (WINSOCK_FD_ISSET (h, &ws_writefds) || (me->write_selected && me->write_ready)) + me->write_ready = true; + if (WINSOCK_FD_ISSET (h, &ws_exceptfds) || (me->except_selected && me->except_ready)) + me->except_ready = true; } - - if (WINSOCK_FD_ISSET (h, &ws_readfds) || (me->read_selected && me->read_ready)) - me->read_ready = true; - if (WINSOCK_FD_ISSET (h, &ws_writefds) || (me->write_selected && me->write_ready)) - me->write_ready = true; - if (WINSOCK_FD_ISSET (h, &ws_exceptfds) || (me->except_selected && me->except_ready)) - me->except_ready = true; return me->read_ready || me->write_ready || me->except_ready; } @@ -1280,17 +1285,17 @@ start_thread_socket (select_record *me, select_stuff *stuff) { HANDLE h = s->fh->get_handle (); select_printf ("Handle %p", h); - if (s->read_selected) + if (s->read_selected && !s->read_ready) { WINSOCK_FD_SET (h, &si->readfds); select_printf ("Added to readfds"); } - if (s->write_selected) + if (s->write_selected && !s->write_ready) { WINSOCK_FD_SET (h, &si->writefds); select_printf ("Added to writefds"); } - if (s->except_selected) + if (s->except_selected && !s->except_ready) { WINSOCK_FD_SET (h, &si->exceptfds); select_printf ("Added to exceptfds"); @@ -1410,7 +1415,7 @@ fhandler_socket::select_write (select_record *s) s->cleanup = socket_cleanup; } s->peek = peek_socket; - s->write_ready = saw_shutdown_write (); + s->write_ready = saw_shutdown_write () || !is_connected (); s->write_selected = true; return s; }