diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 3cdf7251e..e2897b750 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2005-10-22 Corinna Vinschen + + * fhandler.h (class fhandler_socket): Add timeout parameter to wait() + method. + * fhandler_socket.cc (fhandler_socket::connect): Use event driven + technique (prepare/wait/release) to implement interuptible connect. + (fhandler_socket::wait): Add timeout parameter. Allow FD_CONNECT + handling. + * net.cc (cygwin_connect): Remove braindead workaround for allowing + blocking connect. That's entirely in fhandler_socket::connect now. + 2005-10-22 Corinna Vinschen * include/cygwin/version.h: Fix typo. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 961aabc6c..b45d82ff4 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -425,7 +425,7 @@ class fhandler_socket: public fhandler_base } status; bool prepare (HANDLE &event, long event_mask); - int wait (HANDLE event, int flags); + int wait (HANDLE event, int flags, DWORD timeout = 10); void release (HANDLE event); public: diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 420eb627a..f9b913729 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -681,7 +681,20 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) return -1; } - res = ::connect (get_socket (), (struct sockaddr *) &sin, namelen); + if (is_nonblocking ()) + res = ::connect (get_socket (), (struct sockaddr *) &sin, namelen); + else + { + HANDLE evt; + if (prepare (evt, FD_CONNECT)) + { + res = ::connect (get_socket (), (struct sockaddr *) &sin, namelen); + if (res == SOCKET_ERROR + && WSAGetLastError () == WSAEWOULDBLOCK) + res = wait (evt, 0, INFINITE); + release (evt); + } + } if (!res) err = 0; @@ -877,14 +890,14 @@ fhandler_socket::prepare (HANDLE &event, long event_mask) } int -fhandler_socket::wait (HANDLE event, int flags) +fhandler_socket::wait (HANDLE event, int flags, DWORD timeout) { int ret = SOCKET_ERROR; int wsa_err = 0; WSAEVENT ev[2] = { event, signal_arrived }; WSANETWORKEVENTS evts; - switch (WSAWaitForMultipleEvents (2, ev, FALSE, 10, FALSE)) + switch (WSAWaitForMultipleEvents (2, ev, FALSE, timeout, FALSE)) { case WSA_WAIT_TIMEOUT: ret = 0; @@ -910,7 +923,14 @@ fhandler_socket::wait (HANDLE event, int flags) break; } } - if (evts.lNetworkEvents & FD_READ) + if (evts.lNetworkEvents & FD_CONNECT) + { + if (evts.iErrorCode[FD_CONNECT_BIT]) + wsa_err = evts.iErrorCode[FD_CONNECT_BIT]; + else + ret = 0; + } + else if (evts.lNetworkEvents & FD_READ) { if (evts.iErrorCode[FD_READ_BIT]) wsa_err = evts.iErrorCode[FD_READ_BIT]; diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 91ee74a20..eccf0635f 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -775,56 +775,7 @@ cygwin_connect (int fd, const struct sockaddr *name, int namelen) if (efault.faulted (EFAULT) || !fh) res = -1; else - { - bool was_blocking = false; - if (!fh->is_nonblocking ()) - { - int nonblocking = 1; - fh->ioctl (FIONBIO, &nonblocking); - was_blocking = true; - } - res = fh->connect (name, namelen); - if (was_blocking) - { - if (res == -1 && get_errno () == EINPROGRESS) - { - size_t fds_size = howmany (fd + 1, NFDBITS) * sizeof (fd_mask); - fd_set *write_fds = (fd_set *) alloca (fds_size); - fd_set *except_fds = (fd_set *) alloca (fds_size); - memset (write_fds, 0, fds_size); - memset (except_fds, 0, fds_size); - FD_SET (fd, write_fds); - FD_SET (fd, except_fds); - res = cygwin_select (fd + 1, NULL, write_fds, except_fds, NULL); - if (res > 0 && FD_ISSET (fd, except_fds)) - { - res = -1; - for (;;) - { - int err; - int len = sizeof err; - cygwin_getsockopt (fd, SOL_SOCKET, SO_ERROR, - (void *) &err, &len); - if (err) - { - set_errno (err); - break; - } - low_priority_sleep (0); - } - } - else if (res > 0) - res = 0; - else - { - WSASetLastError (WSAEINPROGRESS); - set_winsock_errno (); - } - } - int nonblocking = 0; - fh->ioctl (FIONBIO, &nonblocking); - } - } + res = fh->connect (name, namelen); syscall_printf ("%d = connect (%d, %p, %d)", res, fd, name, namelen);