From fb6b1418e4ccbbcb5697779908229121832f5fb9 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 3 Jun 2003 14:05:17 +0000 Subject: [PATCH] * fhandler_socket.cc (connect_thread): Remove. (accept_thread): Remove. (fhandler_socket::connect): Remove all special blocking handling. (fhandler_socket::accept): Ditto. * net.cc (cygwin_connect): Make blocking sockets temporarily non-blocking and call cygwin_select on them to be interruptible. (cygwin_accept): Ditto. --- winsup/cygwin/ChangeLog | 11 ++++++ winsup/cygwin/fhandler_socket.cc | 56 ++------------------------- winsup/cygwin/net.cc | 65 +++++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 55 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b34f09400..91c68ce6a 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,14 @@ +2003-06-03 Corinna Vinschen + Thomas Pfaff + + * fhandler_socket.cc (connect_thread): Remove. + (accept_thread): Remove. + (fhandler_socket::connect): Remove all special blocking handling. + (fhandler_socket::accept): Ditto. + * net.cc (cygwin_connect): Make blocking sockets temporarily + non-blocking and call cygwin_select on them to be interruptible. + (cygwin_accept): Ditto. + 2003-06-02 Christopher Faylor * spawn.cc (spawn_guts): Don't hang around if the parent doesn't exist. diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index c335f314b..894e980e6 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -33,6 +33,7 @@ #include "sigproc.h" #include "wsock_event.h" #include "cygthread.h" +#include "select.h" #include #define ENTROPY_SOURCE_DEV_UNIT 9 @@ -120,30 +121,6 @@ get_inet_addr (const struct sockaddr *in, int inlen, } } -struct sock_thread_data -{ - int socket; - sockaddr *peer; - int *len; - int ret; -}; - -static DWORD WINAPI -connect_thread (void *arg) -{ - sock_thread_data *std = (sock_thread_data *) arg; - std->ret = ::connect (std->socket, std->peer, *std->len); - return 0; -} - -static DWORD WINAPI -accept_thread (void *arg) -{ - sock_thread_data *std = (sock_thread_data *) arg; - std->ret = ::accept (std->socket, std->peer, std->len); - return 0; -} - /**********************************************************************/ /* fhandler_socket */ @@ -520,7 +497,6 @@ out: int fhandler_socket::connect (const struct sockaddr *name, int namelen) { - BOOL interrupted = FALSE; int res = -1; BOOL secret_check_failed = FALSE; BOOL in_progress = FALSE; @@ -530,18 +506,7 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) if (!get_inet_addr (name, namelen, &sin, &namelen, secret)) return -1; - if (!is_nonblocking ()) - { - sock_thread_data cd = { get_socket (), (sockaddr *) &sin, &namelen, -1 }; - cygthread *thread = new cygthread (connect_thread, &cd, "connect"); - HANDLE waitevt = CreateEvent(&sec_none_nih, FALSE, TRUE, NULL); - interrupted = thread->detach (waitevt); - CloseHandle (waitevt); - if (!interrupted) - res = cd.ret; - } - else - res = ::connect (get_socket (), (sockaddr *) &sin, namelen); + res = ::connect (get_socket (), (sockaddr *) &sin, namelen); if (res) { @@ -596,9 +561,6 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen) else set_connect_state (CONNECTED); - if (interrupted) - set_errno (EINTR); - return res; } @@ -638,19 +600,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len) if (len && ((unsigned) *len < sizeof (struct sockaddr_in))) *len = sizeof (struct sockaddr_in); - if (!is_nonblocking ()) - { - sock_thread_data ad = { get_socket (), peer, len, -1 }; - cygthread *thread = new cygthread (accept_thread, &ad, "accept"); - HANDLE waitevt = CreateEvent(&sec_none_nih, FALSE, TRUE, NULL); - BOOL interrupted = thread->detach (waitevt); - CloseHandle (waitevt); - if (interrupted) - return -1; - res = ad.ret; - } - else - res = ::accept (get_socket (), peer, len); + res = ::accept (get_socket (), peer, len); if ((SOCKET) res == INVALID_SOCKET && WSAGetLastError () == WSAEWOULDBLOCK) in_progress = TRUE; diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index dda0e3113..7890c9bc4 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -773,7 +773,56 @@ cygwin_connect (int fd, const struct sockaddr *name, int namelen) if (__check_invalid_read_ptr_errno (name, namelen) || !fh) res = -1; 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); @@ -1051,7 +1100,19 @@ cygwin_accept (int fd, struct sockaddr *peer, int *len) || !fh) res = -1; else - res = fh->accept (peer, len); + { + if (!fh->is_nonblocking ()) + { + size_t fds_size = howmany (fd + 1, NFDBITS) * sizeof (fd_mask); + fd_set *read_fds = (fd_set *) alloca (fds_size); + memset (read_fds, 0, fds_size); + FD_SET (fd, read_fds); + res = cygwin_select (fd + 1, read_fds, NULL, NULL, NULL); + if (res == -1) + return -1; + } + res = fh->accept (peer, len); + } syscall_printf ("%d = accept (%d, %p, %p)", res, fd, peer, len); return res;