Hi Corinna,
this is a slightly modified version of my proposed solution from
yesterday. Not tested exhaustiv but seems to work pretty well.
Thomas
2003-03-27 Thomas Pfaff <[EMAIL PROTECTED]>
* fhandler_socket.cc (fhandler_socket::connect): Add support for
an interruptable connect.
--- 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;
}