Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2002-07-03 13:20:24 +0400
committerCorinna Vinschen <corinna@vinschen.de>2002-07-03 13:20:24 +0400
commit3c6bd991758fd6a595a527f1875d6658fab441c1 (patch)
tree98d766346ac86859b3c20a2e10a4d7d7be2092e5
parent65604bc18fdafdf99a3e2f46f5476f5627c4cf7d (diff)
* autoload.cc (WSAEventSelect): Define new autoload function.
(WSAEnumNetworkEvents): Ditto. * fhandler_socket.cc (fhandler_socket::accept): If socket is in blocking mode wait for incoming connection and signal.
-rw-r--r--winsup/cygwin/ChangeLog7
-rw-r--r--winsup/cygwin/autoload.cc2
-rw-r--r--winsup/cygwin/fhandler_socket.cc90
3 files changed, 83 insertions, 16 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 9002a0fdd..8f3f2efd4 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,10 @@
+2002-07-03 Thomas Pfaff <tpfaff@gmx.net>
+
+ * autoload.cc (WSAEventSelect): Define new autoload function.
+ (WSAEnumNetworkEvents): Ditto.
+ * fhandler_socket.cc (fhandler_socket::accept): If socket is
+ in blocking mode wait for incoming connection and signal.
+
2002-07-02 Christopher Faylor <cgf@redhat.com>
* cygheap.cc (init_cheap): Rearrange error message.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 5c14ff115..05141e53f 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -480,6 +480,8 @@ LoadDLLfuncEx (WSASendTo, 36, ws2_32, 1)
LoadDLLfuncEx (WSASetEvent, 4, ws2_32, 1)
LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1)
LoadDLLfuncEx (WSAWaitForMultipleEvents, 20, ws2_32, 1)
+LoadDLLfuncEx (WSAEventSelect, 12, ws2_32, 1)
+LoadDLLfuncEx (WSAEnumNetworkEvents, 12, ws2_32, 1)
LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1)
LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1)
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 24e68566e..ffae6b1b8 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -469,6 +469,7 @@ int
fhandler_socket::accept (struct sockaddr *peer, int *len)
{
int res = -1;
+ WSAEVENT ev[2] = { WSA_INVALID_EVENT, signal_arrived };
BOOL secret_check_failed = FALSE;
BOOL in_progress = FALSE;
@@ -492,7 +493,58 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
*len = sizeof (struct sockaddr_in);
- res = ::accept (get_socket (), peer, len); // can't use a blocking call inside a lock
+ if (!is_nonblocking())
+ {
+ ev[0] = WSACreateEvent ();
+
+ if (ev[0] != WSA_INVALID_EVENT &&
+ !WSAEventSelect (get_socket (), ev[0], FD_ACCEPT))
+ {
+ 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 listening socket and
+ switch back to blocking mode */
+ WSAEventSelect (get_socket (), ev[0], 0 );
+ ioctlsocket (get_socket (), FIONBIO, 0);
+
+ switch (wait_result)
+ {
+ case WSA_WAIT_EVENT_0:
+ if (sock_event.lNetworkEvents & FD_ACCEPT)
+ {
+ if (sock_event.iErrorCode[FD_ACCEPT_BIT])
+ {
+ WSASetLastError (sock_event.iErrorCode[FD_ACCEPT_BIT]);
+ set_winsock_errno ();
+ res = -1;
+ goto done;
+ }
+ }
+ /* else; : Should never happen since FD_ACCEPT is the only event
+ that has been selected */
+ break;
+ case WSA_WAIT_EVENT_0 + 1:
+ debug_printf ("signal received during accept");
+ set_errno (EINTR);
+ res = -1;
+ goto done;
+ case WSA_WAIT_FAILED:
+ default: /* Should never happen */
+ WSASetLastError (WSAEFAULT);
+ set_winsock_errno ();
+ res = -1;
+ goto done;
+ }
+ }
+ }
+
+ res = ::accept (get_socket (), peer, len);
if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
WSAGetLastError () == WSAEWOULDBLOCK)
@@ -525,24 +577,30 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
closesocket (res);
set_errno (ECONNABORTED);
res = -1;
- return res;
+ goto done;
}
}
- cygheap_fdnew res_fd;
- if (res_fd < 0)
- /* FIXME: what is correct errno? */;
- else if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
- set_winsock_errno ();
- else
- {
- fhandler_socket* res_fh = fdsock (res_fd, get_name (), res);
- if (get_addr_family () == AF_LOCAL)
- res_fh->set_sun_path (get_sun_path ());
- res_fh->set_addr_family (get_addr_family ());
- res_fh->set_socket_type (get_socket_type ());
- res = res_fd;
- }
+ {
+ cygheap_fdnew res_fd;
+ if (res_fd < 0)
+ /* FIXME: what is correct errno? */;
+ else if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
+ set_winsock_errno ();
+ else
+ {
+ fhandler_socket* res_fh = fdsock (res_fd, get_name (), res);
+ if (get_addr_family () == AF_LOCAL)
+ res_fh->set_sun_path (get_sun_path ());
+ res_fh->set_addr_family (get_addr_family ());
+ res_fh->set_socket_type (get_socket_type ());
+ res = res_fd;
+ }
+ }
+
+done:
+ if (ev[0] != WSA_INVALID_EVENT)
+ WSACloseEvent (ev[0]);
return res;
}