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>2004-03-29 23:41:17 +0400
committerCorinna Vinschen <corinna@vinschen.de>2004-03-29 23:41:17 +0400
commit81f5200ba36593a020f74766827aa25bd2402d75 (patch)
treea3bf0050d984f16079274e475f0d253398cded28
parentc7f060d0dae9beff62f3280addb4afaa4d4f7399 (diff)
* fhandler.h (class fhandler_socket): Add has_been_closed member.
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Initialize has_been_closed to 0. (fhandler_socket::recvfrom): Use new asynchronous I/O driven wsock_event methods. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. * net.cc (wsock_event::prepare): Reimplement using asynchronous I/O. (wsock_event::wait): Ditto. (wsock_event::release): New method. * wsock_event.h (class wsock_event): Remove ovr member. Accomodate new implementation of prepare and wait methods. Add release method.
-rw-r--r--winsup/cygwin/ChangeLog16
-rw-r--r--winsup/cygwin/fhandler.h1
-rw-r--r--winsup/cygwin/fhandler_socket.cc106
-rw-r--r--winsup/cygwin/net.cc77
-rw-r--r--winsup/cygwin/wsock_event.h6
5 files changed, 141 insertions, 65 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ec81ae8a1..aa0951ee9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,19 @@
+2004-03-29 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (class fhandler_socket): Add has_been_closed member.
+ * fhandler_socket.cc (fhandler_socket::fhandler_socket): Initialize
+ has_been_closed to 0.
+ (fhandler_socket::recvfrom): Use new asynchronous I/O driven
+ wsock_event methods.
+ (fhandler_socket::recvmsg): Ditto.
+ (fhandler_socket::sendto): Ditto.
+ (fhandler_socket::sendmsg): Ditto.
+ * net.cc (wsock_event::prepare): Reimplement using asynchronous I/O.
+ (wsock_event::wait): Ditto.
+ (wsock_event::release): New method.
+ * wsock_event.h (class wsock_event): Remove ovr member. Accomodate
+ new implementation of prepare and wait methods. Add release method.
+
2004-03-29 Thomas Pfaff <tpfaff@gmx.net>
* thread.cc (pthread::atforkprepare): Call
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 0b5c71299..a38b50a55 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -377,6 +377,7 @@ class fhandler_socket: public fhandler_base
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
char *sun_path;
int had_connect_or_listen;
+ int has_been_closed;
public:
fhandler_socket ();
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 63f28fb27..0c3058867 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -122,7 +122,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
/* fhandler_socket */
fhandler_socket::fhandler_socket ()
- : fhandler_base (), sun_path (NULL)
+ : fhandler_base (), sun_path (NULL), has_been_closed (0)
{
set_need_fork_fixup ();
prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
@@ -726,19 +726,28 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
{
WSABUF wsabuf = { len, (char *) ptr };
- if (is_nonblocking ())
+ if (is_nonblocking () || has_been_closed)
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
from, fromlen,
NULL, NULL);
else
{
wsock_event wsock_evt;
- res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
- from, fromlen,
- wsock_evt.prepare (), NULL);
-
- if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
- ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
+ long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
+ if (wsock_evt.prepare (get_socket (), evt))
+ {
+ do
+ {
+ if (!(res = wsock_evt.wait (get_socket (), has_been_closed)))
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret,
+ (DWORD *) &flags, from, fromlen,
+ NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !has_been_closed);
+ wsock_evt.release (get_socket ());
+ }
}
}
@@ -844,7 +853,7 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
DWORD ret;
- if (is_nonblocking ())
+ if (is_nonblocking () || has_been_closed)
res = WSARecvFrom (get_socket (),
wsabuf, iovcnt, &ret, (DWORD *) &flags,
from, fromlen,
@@ -852,13 +861,21 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
else
{
wsock_event wsock_evt;
- res = WSARecvFrom (get_socket (),
- wsabuf, iovcnt, &ret, (DWORD *) &flags,
- from, fromlen,
- wsock_evt.prepare (), NULL);
-
- if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
- ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
+ long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
+ if (wsock_evt.prepare (get_socket (), evt))
+ {
+ do
+ {
+ if (!(res = wsock_evt.wait (get_socket (), has_been_closed)))
+ res = WSARecvFrom (get_socket (), wsabuf, iovcnt, &ret,
+ (DWORD *) &flags, from, fromlen,
+ NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !has_been_closed);
+ wsock_evt.release (get_socket ());
+ }
}
if (res == SOCKET_ERROR)
@@ -915,7 +932,7 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
{
WSABUF wsabuf = { len, (char *) ptr };
- if (is_nonblocking ())
+ if (is_nonblocking () || has_been_closed)
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL), tolen,
@@ -923,13 +940,26 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
else
{
wsock_event wsock_evt;
- res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
- flags & MSG_WINMASK,
- (to ? (const struct sockaddr *) &sin : NULL), tolen,
- wsock_evt.prepare (), NULL);
-
- if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
- ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
+ if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
+ {
+ do
+ {
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sin : NULL),
+ tolen, NULL, NULL);
+ if (res != SOCKET_ERROR
+ || WSAGetLastError () != WSAEWOULDBLOCK)
+ break;
+ if (ret > 0)
+ {
+ res = 0;
+ break;
+ }
+ }
+ while (!(res = wsock_evt.wait (get_socket (), has_been_closed)));
+ wsock_evt.release (get_socket ());
+ }
}
}
@@ -1041,7 +1071,7 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
DWORD ret;
- if (is_nonblocking ())
+ if (is_nonblocking () || has_been_closed)
res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
(struct sockaddr *) msg->msg_name,
msg->msg_namelen,
@@ -1049,13 +1079,25 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
else
{
wsock_event wsock_evt;
- res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
- (struct sockaddr *) msg->msg_name,
- msg->msg_namelen,
- wsock_evt.prepare (), NULL);
-
- if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
- ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
+ if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
+ {
+ do
+ {
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret,
+ flags, (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen, NULL, NULL);
+ if (res != SOCKET_ERROR
+ || WSAGetLastError () != WSAEWOULDBLOCK)
+ break;
+ if (ret > 0)
+ {
+ res = 0;
+ break;
+ }
+ }
+ while (!(res = wsock_evt.wait (get_socket (), has_been_closed)));
+ wsock_evt.release (get_socket ());
+ }
}
if (res == SOCKET_ERROR)
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 8c4090b28..3d76a433b 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -50,58 +50,75 @@ extern "C"
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
-LPWSAOVERLAPPED
-wsock_event::prepare ()
+bool
+wsock_event::prepare (int sock, long event_mask)
{
- LPWSAOVERLAPPED ret = NULL;
-
SetLastError (0);
- if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
+ if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT
+ && WSAEventSelect (sock, event, event_mask) == SOCKET_ERROR)
{
- memset (&ovr, 0, sizeof ovr);
- ovr.hEvent = event;
- ret = &ovr;
+ debug_printf ("WSAEventSelect: %E");
+ WSACloseEvent (event);
+ event = WSA_INVALID_EVENT;
}
- else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
- WSASetLastError (0);
-
- debug_printf ("%d = wsock_event::prepare ()", ret);
- return ret;
+ return event != WSA_INVALID_EVENT;
}
int
-wsock_event::wait (int socket, LPDWORD flags)
+wsock_event::wait (int sock, int &closed)
{
int ret = -1;
+ DWORD wsa_err = 0;
WSAEVENT ev[2] = { event, signal_arrived };
- DWORD len;
-
switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
{
case WSA_WAIT_EVENT_0:
- if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags))
- ret = (int) len;
- break;
- case WSA_WAIT_EVENT_0 + 1:
- if (!CancelIo ((HANDLE) socket))
+ WSANETWORKEVENTS evts;
+ memset (&evts, 0, sizeof evts);
+ WSAEnumNetworkEvents (sock, event, &evts);
+ if (evts.lNetworkEvents & FD_READ)
+ {
+ if (evts.iErrorCode[FD_READ_BIT])
+ wsa_err = evts.iErrorCode[FD_READ_BIT];
+ else
+ ret = 0;
+ }
+ else if (evts.lNetworkEvents & FD_WRITE)
+ {
+ if (evts.iErrorCode[FD_WRITE_BIT])
+ wsa_err = evts.iErrorCode[FD_WRITE_BIT];
+ else
+ ret = 0;
+ }
+ if (evts.lNetworkEvents & FD_CLOSE)
{
- debug_printf ("CancelIo() %E, fallback to blocking io");
- WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags);
+ closed = 1;
+ if (!wsa_err && evts.iErrorCode[FD_CLOSE_BIT])
+ wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
+ else
+ ret = 0;
}
- else
- WSASetLastError (WSAEINTR);
+ if (wsa_err)
+ WSASetLastError (wsa_err);
break;
- case WSA_WAIT_FAILED:
+ case WSA_WAIT_EVENT_0 + 1:
+ WSASetLastError (WSAEINTR);
break;
- default: /* Should be impossible. *LOL* */
+ default:
WSASetLastError (WSAEFAULT);
- break;
}
- WSACloseEvent (event);
- event = NULL;
return ret;
}
+void
+wsock_event::release (int sock)
+{
+ WSAEventSelect (sock, event, 0);
+ WSACloseEvent (event);
+ unsigned long non_block = 0;
+ ioctlsocket (sock, FIONBIO, &non_block);
+}
+
WSADATA wsadata;
static fhandler_socket *
diff --git a/winsup/cygwin/wsock_event.h b/winsup/cygwin/wsock_event.h
index 3f8638134..9a1f07ac1 100644
--- a/winsup/cygwin/wsock_event.h
+++ b/winsup/cygwin/wsock_event.h
@@ -14,7 +14,6 @@ details. */
class wsock_event
{
WSAEVENT event;
- WSAOVERLAPPED ovr;
public:
wsock_event () : event (NULL) {};
~wsock_event ()
@@ -25,8 +24,9 @@ public:
};
/* The methods are implemented in net.cc */
- LPWSAOVERLAPPED prepare ();
- int wait (int socket, LPDWORD flags);
+ bool prepare (int sock, long event_mask);
+ int wait (int sock, int &closed);
+ void release (int sock);
};
#endif /* __WSOCK_EVENT_H__ */