aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2004-05-07 07:51:31 +0000
committerCorinna Vinschen <corinna@vinschen.de>2004-05-07 07:51:31 +0000
commit3e101fb2cd57d46020748deb607c99fd6e5be3bf (patch)
tree81e2da440cf03b3eea979e291aac5b305dda9253
parentdab22ff6e640d81b5b0b0b2e075069c8bf092b31 (diff)
downloadnewlib-3e101fb2cd57d46020748deb607c99fd6e5be3bf.zip
newlib-3e101fb2cd57d46020748deb607c99fd6e5be3bf.tar.gz
newlib-3e101fb2cd57d46020748deb607c99fd6e5be3bf.tar.bz2
Revert code reversion from 2004-04-03. So, revert to async I/O again.
* fhandler.h (status): Add "closed" flag. (prepare): New method declaration. (wait): Ditto. (release): Ditto. * fhandler_socket.cc: Don't include wsock_event.h. (fhandler_socket::prepare): New method, moved from wsock_event. (fhandler_socket::wait): Ditto. (fhandler_socket::release): New method. (fhandler_socket::recvfrom): Simplify loop. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. * net.cc: Don't include wsock_event.h. (wsock_event::prepare): Remove. (wsock_event::wait): Ditto. * wsock_event.h: Remove.
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/fhandler.h8
-rw-r--r--winsup/cygwin/fhandler_socket.cc218
-rw-r--r--winsup/cygwin/net.cc56
-rw-r--r--winsup/cygwin/wsock_event.h32
5 files changed, 193 insertions, 143 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 62c23f9..6c5d202 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,6 +1,22 @@
-2004-05-06 Christopher Faylor <cgf@alum.bu.edu>
-
- *
+2004-05-07 Corinna Vinschen <corinna@vinschen.de>
+
+ Revert code reversion from 2004-04-03. So, revert to async I/O again.
+ * fhandler.h (status): Add "closed" flag.
+ (prepare): New method declaration.
+ (wait): Ditto.
+ (release): Ditto.
+ * fhandler_socket.cc: Don't include wsock_event.h.
+ (fhandler_socket::prepare): New method, moved from wsock_event.
+ (fhandler_socket::wait): Ditto.
+ (fhandler_socket::release): New method.
+ (fhandler_socket::recvfrom): Simplify loop.
+ (fhandler_socket::recvmsg): Ditto.
+ (fhandler_socket::sendto): Ditto.
+ (fhandler_socket::sendmsg): Ditto.
+ * net.cc: Don't include wsock_event.h.
+ (wsock_event::prepare): Remove.
+ (wsock_event::wait): Ditto.
+ * wsock_event.h: Remove.
2004-05-06 Christopher Faylor <cgf@alum.bu.edu>
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3a14434..acdd09f 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -340,14 +340,19 @@ class fhandler_socket: public fhandler_base
unsigned async_io : 1; /* async I/O */
unsigned saw_shutdown_read : 1; /* Socket saw a SHUT_RD */
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
+ unsigned closed : 1;
unsigned connect_state : 2;
public:
status_flags () :
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
- connect_state (unconnected)
+ closed (0), connect_state (unconnected)
{}
} status;
+ bool prepare (HANDLE &event, long event_mask);
+ int wait (HANDLE event);
+ void release (HANDLE event);
+
public:
fhandler_socket ();
~fhandler_socket ();
@@ -357,6 +362,7 @@ class fhandler_socket: public fhandler_base
IMPLEMENT_STATUS_FLAG (bool, async_io)
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_read)
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
+ IMPLEMENT_STATUS_FLAG (bool, closed)
IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
int bind (const struct sockaddr *name, int namelen);
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 5016700..dedbd34 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -30,7 +30,6 @@
#include "dtable.h"
#include "cygheap.h"
#include "sigproc.h"
-#include "wsock_event.h"
#include "cygthread.h"
#include "select.h"
#include <unistd.h>
@@ -695,6 +694,95 @@ fhandler_socket::getpeername (struct sockaddr *name, int *namelen)
return res;
}
+bool
+fhandler_socket::prepare (HANDLE &event, long event_mask)
+{
+ WSASetLastError (0);
+ closed (false);
+ if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
+ {
+ debug_printf ("WSACreateEvent: %E");
+ return false;
+ }
+ if (WSAEventSelect (get_socket (), event, event_mask) == SOCKET_ERROR)
+ {
+ debug_printf ("WSAEventSelect: %E");
+ return false;
+ }
+ return true;
+}
+
+int
+fhandler_socket::wait (HANDLE event)
+{
+ int ret = SOCKET_ERROR;
+ int wsa_err = 0;
+ WSAEVENT ev[2] = { event, signal_arrived };
+ WSANETWORKEVENTS evts;
+
+ switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
+ {
+ case WSA_WAIT_EVENT_0:
+ if (!WSAEnumNetworkEvents (get_socket (), event, &evts))
+ {
+ if (!evts.lNetworkEvents)
+ {
+ ret = 0;
+ break;
+ }
+ 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)
+ {
+ closed (true);
+ if (!wsa_err)
+ {
+ if (evts.iErrorCode[FD_CLOSE_BIT])
+ wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
+ else
+ ret = 0;
+ }
+ }
+ if (wsa_err)
+ WSASetLastError (wsa_err);
+ }
+ break;
+ case WSA_WAIT_EVENT_0 + 1:
+ WSASetLastError (WSAEINTR);
+ break;
+ default:
+ WSASetLastError (WSAEFAULT);
+ break;
+ }
+ return ret;
+}
+
+void
+fhandler_socket::release (HANDLE event)
+{
+ int last_err = WSAGetLastError ();
+ /* KB 168349: NT4 fails if the event parameter is not NULL. */
+ WSAEventSelect (get_socket (), NULL, 0);
+ unsigned long non_block = 0;
+ if (ioctlsocket (get_socket (), FIONBIO, &non_block))
+ debug_printf ("return to blocking failed: %d", WSAGetLastError ());
+ else
+ WSASetLastError (last_err);
+ WSACloseEvent (event);
+}
+
int
fhandler_socket::readv (const struct iovec *const iov, const int iovcnt,
ssize_t tot)
@@ -716,7 +804,7 @@ int
fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
struct sockaddr *from, int *fromlen)
{
- int res;
+ int res = SOCKET_ERROR;
DWORD ret;
flags &= MSG_WINMASK;
@@ -728,19 +816,26 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
{
WSABUF wsabuf = { len, (char *) ptr };
- if (is_nonblocking ())
- res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
- from, fromlen,
- NULL, NULL);
+ if (is_nonblocking () || closed () || async_io ())
+ res = WSARecvFrom (get_socket (), &wsabuf, 1, (ret = 0, &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);
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ)))
+ {
+ do
+ {
+ res = WSARecvFrom (get_socket (), &wsabuf, 1,
+ &ret, (DWORD *) &flags,
+ from, fromlen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !closed ()
+ && !(res = wait (evt)));
+ release (evt);
+ }
}
}
@@ -778,7 +873,7 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
struct sockaddr *from = (struct sockaddr *) msg->msg_name;
int *fromlen = from ? &msg->msg_namelen : NULL;
- int res;
+ int res = SOCKET_ERROR;
if (!winsock2_active)
{
@@ -845,21 +940,27 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
DWORD ret;
- if (is_nonblocking ())
+ if (is_nonblocking () || closed () || async_io ())
res = WSARecvFrom (get_socket (),
- wsabuf, iovcnt, &ret, (DWORD *) &flags,
- from, fromlen,
- NULL, NULL);
+ wsabuf, iovcnt, (ret = 0, &ret), (DWORD *) &flags,
+ from, fromlen, NULL, NULL);
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);
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ)))
+ {
+ do
+ {
+ res = WSARecvFrom (get_socket (), wsabuf, iovcnt,
+ &ret, (DWORD *) &flags,
+ from, fromlen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !closed ()
+ && !(res = wait (evt)));
+ release (evt);
+ }
}
if (res == SOCKET_ERROR)
@@ -904,7 +1005,7 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
if (to && !get_inet_addr (to, tolen, &sin, &tolen))
return SOCKET_ERROR;
- int res;
+ int res = SOCKET_ERROR;
DWORD ret;
if (!winsock2_active)
@@ -915,21 +1016,29 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
{
WSABUF wsabuf = { len, (char *) ptr };
- if (is_nonblocking ())
- res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ if (is_nonblocking () || closed () || async_io ())
+ res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
flags & MSG_WINMASK,
(to ? (const struct sockaddr *) &sin : NULL), tolen,
NULL, NULL);
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);
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | FD_WRITE))
+ {
+ do
+ {
+ res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
+ flags & MSG_WINMASK,
+ (to ? (const struct sockaddr *) &sin : NULL),
+ tolen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !(res = wait (evt))
+ && !closed ());
+ release (evt);
+ }
}
}
@@ -969,7 +1078,7 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
struct iovec *const iov = msg->msg_iov;
const int iovcnt = msg->msg_iovlen;
- int res;
+ int res = SOCKET_ERROR;
if (!winsock2_active)
{
@@ -1038,21 +1147,28 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
DWORD ret;
- if (is_nonblocking ())
- res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
- (struct sockaddr *) msg->msg_name,
- msg->msg_namelen,
- NULL, NULL);
+ if (is_nonblocking () || closed () || async_io ())
+ res = WSASendTo (get_socket (), wsabuf, iovcnt, (ret = 0, &ret),
+ flags, (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen, NULL, NULL);
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);
+ HANDLE evt;
+ if (prepare (evt, FD_CLOSE | FD_WRITE))
+ {
+ do
+ {
+ res = WSASendTo (get_socket (), wsabuf, iovcnt,
+ &ret, flags,
+ (struct sockaddr *) msg->msg_name,
+ msg->msg_namelen, NULL, NULL);
+ }
+ while (res == SOCKET_ERROR
+ && WSAGetLastError () == WSAEWOULDBLOCK
+ && !(res = wait (evt))
+ && !closed ());
+ release (evt);
+ }
}
if (res == SOCKET_ERROR)
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 3de2c0a..58c3a9f 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -35,7 +35,6 @@ details. */
#include "sigproc.h"
#include "pinfo.h"
#include "registry.h"
-#include "wsock_event.h"
#include "cygtls.h"
extern "C"
@@ -50,61 +49,6 @@ extern "C"
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
-LPWSAOVERLAPPED
-wsock_event::prepare ()
-{
- LPWSAOVERLAPPED ret = NULL;
-
- SetLastError (0);
- if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
- {
- memset (&ovr, 0, sizeof ovr);
- ovr.hEvent = event;
- ret = &ovr;
- }
- else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
- WSASetLastError (0);
-
- debug_printf ("%d = wsock_event::prepare ()", ret);
- return ret;
-}
-
-int
-wsock_event::wait (int socket, LPDWORD flags)
-{
- int ret = SOCKET_ERROR;
- 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))
- {
- debug_printf ("CancelIo() %E, fallback to blocking io");
- WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags);
- }
- else if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags)
- && len > 0)
- ret = (int) len;
- else
- WSASetLastError (WSAEINTR);
- break;
- case WSA_WAIT_FAILED:
- break;
- default: /* Should be impossible. *LOL* */
- WSASetLastError (WSAEFAULT);
- break;
- }
- WSACloseEvent (event);
- event = NULL;
- return ret;
-}
-
WSADATA wsadata;
static fhandler_socket *
diff --git a/winsup/cygwin/wsock_event.h b/winsup/cygwin/wsock_event.h
deleted file mode 100644
index 3f86381..0000000
--- a/winsup/cygwin/wsock_event.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* wsock_event.h: Defining the wsock_event class
-
- Copyright 2002 Red Hat, Inc.
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#ifndef __WSOCK_EVENT_H__
-#define __WSOCK_EVENT_H__
-
-class wsock_event
-{
- WSAEVENT event;
- WSAOVERLAPPED ovr;
-public:
- wsock_event () : event (NULL) {};
- ~wsock_event ()
- {
- if (event)
- WSACloseEvent (event);
- event = NULL;
- };
-
- /* The methods are implemented in net.cc */
- LPWSAOVERLAPPED prepare ();
- int wait (int socket, LPDWORD flags);
-};
-
-#endif /* __WSOCK_EVENT_H__ */