diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2004-05-07 07:51:31 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2004-05-07 07:51:31 +0000 |
commit | 3e101fb2cd57d46020748deb607c99fd6e5be3bf (patch) | |
tree | 81e2da440cf03b3eea979e291aac5b305dda9253 | |
parent | dab22ff6e640d81b5b0b0b2e075069c8bf092b31 (diff) | |
download | newlib-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/ChangeLog | 22 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 8 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 218 | ||||
-rw-r--r-- | winsup/cygwin/net.cc | 56 | ||||
-rw-r--r-- | winsup/cygwin/wsock_event.h | 32 |
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__ */ |