* 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.
This commit is contained in:
Corinna Vinschen 2005-10-22 15:11:49 +00:00
parent ecebee4838
commit 152a9caf58
4 changed files with 37 additions and 55 deletions

View File

@ -1,3 +1,14 @@
2005-10-22 Corinna Vinschen <corinna@vinschen.de>
* 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 <corinna@vinschen.de> 2005-10-22 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/version.h: Fix typo. * include/cygwin/version.h: Fix typo.

View File

@ -425,7 +425,7 @@ class fhandler_socket: public fhandler_base
} status; } status;
bool prepare (HANDLE &event, long event_mask); 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); void release (HANDLE event);
public: public:

View File

@ -681,7 +681,20 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
return -1; 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) if (!res)
err = 0; err = 0;
@ -877,14 +890,14 @@ fhandler_socket::prepare (HANDLE &event, long event_mask)
} }
int int
fhandler_socket::wait (HANDLE event, int flags) fhandler_socket::wait (HANDLE event, int flags, DWORD timeout)
{ {
int ret = SOCKET_ERROR; int ret = SOCKET_ERROR;
int wsa_err = 0; int wsa_err = 0;
WSAEVENT ev[2] = { event, signal_arrived }; WSAEVENT ev[2] = { event, signal_arrived };
WSANETWORKEVENTS evts; WSANETWORKEVENTS evts;
switch (WSAWaitForMultipleEvents (2, ev, FALSE, 10, FALSE)) switch (WSAWaitForMultipleEvents (2, ev, FALSE, timeout, FALSE))
{ {
case WSA_WAIT_TIMEOUT: case WSA_WAIT_TIMEOUT:
ret = 0; ret = 0;
@ -910,7 +923,14 @@ fhandler_socket::wait (HANDLE event, int flags)
break; 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]) if (evts.iErrorCode[FD_READ_BIT])
wsa_err = evts.iErrorCode[FD_READ_BIT]; wsa_err = evts.iErrorCode[FD_READ_BIT];

View File

@ -775,56 +775,7 @@ cygwin_connect (int fd, const struct sockaddr *name, int namelen)
if (efault.faulted (EFAULT) || !fh) if (efault.faulted (EFAULT) || !fh)
res = -1; res = -1;
else else
{ res = fh->connect (name, namelen);
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);
}
}
syscall_printf ("%d = connect (%d, %p, %d)", res, fd, name, namelen); syscall_printf ("%d = connect (%d, %p, %d)", res, fd, name, namelen);