OSDN Git Service

* fhandler.h (class fhandler_socket): Remove has_been_closed member.
authorcorinna <corinna>
Sat, 3 Apr 2004 19:07:58 +0000 (19:07 +0000)
committercorinna <corinna>
Sat, 3 Apr 2004 19:07:58 +0000 (19:07 +0000)
* fhandler_socket.cc (fhandler_socket::recvfrom): Revert to
overlapped I/O.
(fhandler_socket::recvmsg): Ditto.
(fhandler_socket::sendto): Ditto.
(fhandler_socket::sendmsg): Ditto.
* net.cc (wsock_event::prepare): Ditto.
(wsock_event::wait): Ditto.  Evaluate overlapped result also after
calling CancelIo (thanks to Patrick Samson <p_samson@yahoo.com>).
(wsock_event::release): Remove.
* wsock_event.h: Revert to overlapped I/O.

winsup/cygwin/ChangeLog
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_socket.cc
winsup/cygwin/net.cc
winsup/cygwin/wsock_event.h

index 1cf4152..af6cd04 100644 (file)
@@ -1,3 +1,17 @@
+2004-04-03  Corinna Vinschen  <corinna@vinschen.de>
+
+       * fhandler.h (class fhandler_socket): Remove has_been_closed member.
+       * fhandler_socket.cc (fhandler_socket::recvfrom): Revert to
+       overlapped I/O.
+       (fhandler_socket::recvmsg): Ditto.
+       (fhandler_socket::sendto): Ditto.
+       (fhandler_socket::sendmsg): Ditto.
+       * net.cc (wsock_event::prepare): Ditto.
+       (wsock_event::wait): Ditto.  Evaluate overlapped result also after
+       calling CancelIo (thanks to Patrick Samson <p_samson@yahoo.com>).
+       (wsock_event::release): Remove.
+       * wsock_event.h: Revert to overlapped I/O.
+
 2004-04-02  Corinna Vinschen  <corinna@vinschen.de>
 
        * net.cc (wsock_event::release): Use NULL handle in call to
index a38b50a..0b5c712 100644 (file)
@@ -377,7 +377,6 @@ 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 ();
index 7f028ba..79e63e1 100644 (file)
@@ -122,7 +122,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
 /* fhandler_socket */
 
 fhandler_socket::fhandler_socket ()
-  : fhandler_base (), sun_path (NULL), has_been_closed (0)
+  : fhandler_base (), sun_path (NULL)
 {
   set_need_fork_fixup ();
   prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
@@ -714,7 +714,7 @@ int
 fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
                           struct sockaddr *from, int *fromlen)
 {
-  int res = SOCKET_ERROR;
+  int res;
   DWORD ret;
 
   flags &= MSG_WINMASK;
@@ -726,28 +726,19 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
     {
       WSABUF wsabuf = { len, (char *) ptr };
 
-      if (is_nonblocking () || has_been_closed)
-       res = WSARecvFrom (get_socket (), &wsabuf, 1, (ret = 0, &ret),
-                          (DWORD *) &flags, from, fromlen, NULL, NULL);
+      if (is_nonblocking ())
+       res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
+                          from, fromlen,
+                          NULL, NULL);
       else
        {
          wsock_event wsock_evt;
-         long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
-         if (wsock_evt.prepare (get_socket (), evt))
-           {
-              do
-                {
-                 res = WSARecvFrom (get_socket (), &wsabuf, 1,
-                                    (ret = 0, &ret), (DWORD *) &flags,
-                                    from, fromlen, NULL, NULL);
-                }
-              while (res == SOCKET_ERROR
-                     && WSAGetLastError () == WSAEWOULDBLOCK
-                    && !has_been_closed
-                    && !(res = wsock_evt.wait (get_socket (),
-                                               has_been_closed)));
-             wsock_evt.release (get_socket ());
-           }
+         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);
        }
     }
 
@@ -785,7 +776,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 = SOCKET_ERROR;
+  int res;
 
   if (!winsock2_active)
     {
@@ -852,29 +843,21 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
 
       DWORD ret;
 
-      if (is_nonblocking () || has_been_closed)
+      if (is_nonblocking ())
        res = WSARecvFrom (get_socket (),
-                          wsabuf, iovcnt, (ret = 0, &ret), (DWORD *) &flags,
-                          from, fromlen, NULL, NULL);
+                          wsabuf, iovcnt, &ret, (DWORD *) &flags,
+                          from, fromlen,
+                          NULL, NULL);
       else
        {
          wsock_event wsock_evt;
-         long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
-         if (wsock_evt.prepare (get_socket (), evt))
-           {
-              do
-                {
-                 res = WSARecvFrom (get_socket (), wsabuf, iovcnt,
-                                    (ret = 0, &ret), (DWORD *) &flags,
-                                    from, fromlen, NULL, NULL);
-                }
-              while (res == SOCKET_ERROR
-                    && WSAGetLastError () == WSAEWOULDBLOCK
-                    && !has_been_closed
-                    && !(res = wsock_evt.wait (get_socket (),
-                                               has_been_closed)));
-             wsock_evt.release (get_socket ());
-           }
+         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);
        }
 
       if (res == SOCKET_ERROR)
@@ -917,9 +900,9 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
   sockaddr_in sin;
 
   if (to && !get_inet_addr (to, tolen, &sin, &tolen))
-    return -1;
+    return SOCKET_ERROR;
 
-  int res = SOCKET_ERROR;
+  int res;
   DWORD ret;
 
   if (!winsock2_active)
@@ -930,35 +913,21 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
     {
       WSABUF wsabuf = { len, (char *) ptr };
 
-      if (is_nonblocking () || has_been_closed)
-       res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
+      if (is_nonblocking ())
+       res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
                         flags & MSG_WINMASK,
                         (to ? (const struct sockaddr *) &sin : NULL), tolen,
                         NULL, NULL);
       else
        {
          wsock_event wsock_evt;
-         if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
-           {
-             do 
-               {
-                 res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &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))
-                    && !has_been_closed);
-             wsock_evt.release (get_socket ());
-           }
+         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);
        }
     }
 
@@ -998,7 +967,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 = SOCKET_ERROR;
+  int res;
 
   if (!winsock2_active)
     {
@@ -1067,34 +1036,21 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
 
       DWORD ret;
 
-      if (is_nonblocking () || has_been_closed)
-       res = WSASendTo (get_socket (), wsabuf, iovcnt, (ret = 0, &ret),
-                        flags, (struct sockaddr *) msg->msg_name,
-                        msg->msg_namelen, NULL, NULL);
+      if (is_nonblocking ())
+       res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
+                        (struct sockaddr *) msg->msg_name,
+                        msg->msg_namelen,
+                        NULL, NULL);
       else
        {
          wsock_event wsock_evt;
-         if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
-           {
-              do
-                {
-                 res = WSASendTo (get_socket (), wsabuf, iovcnt,
-                                  (ret = 0, &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))
-                    && !has_been_closed);
-             wsock_evt.release (get_socket ());
-           }
+         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 (res == SOCKET_ERROR)
index 32b9f1f..c0c5b84 100644 (file)
@@ -50,83 +50,59 @@ extern "C"
   int sscanf (const char *, const char *, ...);
 }                              /* End of "C" section */
 
-bool
-wsock_event::prepare (int sock, long event_mask)
+LPWSAOVERLAPPED
+wsock_event::prepare ()
 {
-  WSASetLastError (0);
-  if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
-    debug_printf ("WSACreateEvent: %E");
-  else if (WSAEventSelect (sock, event, event_mask) == SOCKET_ERROR)
+  LPWSAOVERLAPPED ret = NULL;
+
+  SetLastError (0);
+  if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
     {
-      debug_printf ("WSAEventSelect: %E");
-      WSACloseEvent (event);
-      event = WSA_INVALID_EVENT;
+      memset (&ovr, 0, sizeof ovr);
+      ovr.hEvent = event;
+      ret = &ovr;
     }
-  return 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;
 }
 
 int
-wsock_event::wait (int sock, int &closed)
+wsock_event::wait (int socket, LPDWORD flags)
 {
   int ret = SOCKET_ERROR;
-  int wsa_err = 0;
   WSAEVENT ev[2] = { event, signal_arrived };
+  DWORD len;
+
   switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
     {
       case WSA_WAIT_EVENT_0:
-        WSANETWORKEVENTS evts;
-       if (!WSAEnumNetworkEvents (sock, event, &evts))
+       if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags))
+         ret = (int) len;
+       break;
+      case WSA_WAIT_EVENT_0 + 1:
+       if (!CancelIo ((HANDLE) socket))
          {
-           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 = 1;
-               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);
+           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_EVENT_0 + 1:
-        WSASetLastError (WSAEINTR);
+      case WSA_WAIT_FAILED:
        break;
-      default:
+      default:                 /* Should be impossible. *LOL* */
        WSASetLastError (WSAEFAULT);
+       break;
     }
-  return ret;
-}
-
-void
-wsock_event::release (int sock)
-{
-  int last_err = WSAGetLastError ();
-  /* KB 168349: NT4 fails if the event parameter is not NULL. */
-  WSAEventSelect (sock, NULL, 0);
   WSACloseEvent (event);
-  unsigned long non_block = 0;
-  if (ioctlsocket (sock, FIONBIO, &non_block))
-    debug_printf ("return to blocking failed: %d", WSAGetLastError ());
-  else
-    WSASetLastError (last_err);
+  event = NULL;
+  return ret;
 }
 
 WSADATA wsadata;
index 5383a79..3f86381 100644 (file)
@@ -14,13 +14,19 @@ details. */
 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 */
-  bool prepare (int sock, long event_mask);
-  int wait (int sock, int &closed);
-  void release (int sock);
+  LPWSAOVERLAPPED prepare ();
+  int wait (int socket, LPDWORD flags);
 };
 
 #endif /* __WSOCK_EVENT_H__ */