--- fhandler_socket.cc.org 2003-02-27 16:14:49.000000000 +0100 +++ fhandler_socket.cc 2003-02-27 16:15:59.000000000 +0100 @@ -431,6 +431,8 @@ out: int fhandler_socket::connect (const struct sockaddr *name, int namelen) { + WSAEVENT ev[2] = { WSA_INVALID_EVENT, signal_arrived }; + BOOL interrupted = FALSE; int res = -1; BOOL secret_check_failed = FALSE; BOOL in_progress = FALSE; @@ -440,12 +442,63 @@ fhandler_socket::connect (const struct s if (!get_inet_addr (name, namelen, &sin, &namelen, secret)) return -1; + if (!is_nonblocking () && !is_connect_pending ()) + { + ev[0] = WSACreateEvent (); + WSAEventSelect (get_socket (), ev[0], FD_CONNECT); + } + res = ::connect (get_socket (), (sockaddr *) &sin, namelen); + if (res && !is_nonblocking () && !is_connect_pending () && + WSAGetLastError () == WSAEWOULDBLOCK) + { + + WSANETWORKEVENTS sock_event; + int wait_result; + + wait_result = WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE); + + if (wait_result == WSA_WAIT_EVENT_0) + WSAEnumNetworkEvents (get_socket (), ev[0], &sock_event); + + /* Unset events for connecting socket and + switch back to blocking mode */ + WSAEventSelect (get_socket (), ev[0], 0); + unsigned long nonblocking = 0; + ioctlsocket (get_socket (), FIONBIO, &nonblocking); + + switch (wait_result) + { + case WSA_WAIT_EVENT_0: + if (sock_event.lNetworkEvents & FD_CONNECT) + { + if (sock_event.iErrorCode[FD_CONNECT_BIT]) + WSASetLastError (sock_event.iErrorCode[FD_CONNECT_BIT]); + else + res = 0; + } + /* else; : Should never happen since FD_CONNECT is the only + event that has been selected */ + break; + + case WSA_WAIT_EVENT_0 + 1: + debug_printf ("signal received during connect"); + WSASetLastError (WSAEINPROGRESS); + interrupted = TRUE; + break; + + case WSA_WAIT_FAILED: + default: /* Should never happen */ + WSASetLastError (WSAEFAULT); + break; + } + } + if (res) { /* Special handling for connect to return the correct error code when called on a non-blocking socket. */ - if (is_nonblocking ()) + if (is_nonblocking () || is_connect_pending ()) { DWORD err = WSAGetLastError (); if (err == WSAEWOULDBLOCK || err == WSAEALREADY) @@ -493,6 +546,13 @@ fhandler_socket::connect (const struct s set_connect_state (CONNECT_PENDING); else set_connect_state (CONNECTED); + + if (ev[0] != WSA_INVALID_EVENT) + WSACloseEvent (ev[0]); + + if (interrupted) + set_errno (EINTR); + return res; }