[glib] socket/win32: flush pending read before signaling HUP



commit 704a2ca02de0430786114e7d9bf7aa772c40b934
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date:   Fri Feb 10 02:02:29 2012 +0100

    socket/win32: flush pending read before signaling HUP
    
    Unix and Windows gio GSocket behaves differently when the socket is
    closed by the peer. On Unix, the client receives pending data before
    receiving HUP. But on Windows, the HUP may come before, resulting in
    unreliable and racy code. We should have same behaviour on all
    platforms.
    
    According to MSDN documentation: "an application should check for
    remaining data upon receipt of FD_CLOSE to avoid any possibility of
    losing data."
    
    https://bugzilla.gnome.org/show_bug.cgi?id=669810

 gio/gsocket.c |   22 ++++++++++++++++++++--
 1 files changed, 20 insertions(+), 2 deletions(-)
---
diff --git a/gio/gsocket.c b/gio/gsocket.c
index f9eee4f..c6a9137 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -3040,8 +3040,26 @@ update_condition (GSocket *socket)
   if (socket->priv->current_events & (FD_READ | FD_ACCEPT))
     condition |= G_IO_IN;
 
-  if (socket->priv->current_events & FD_CLOSE ||
-      socket->priv->closed)
+  if (socket->priv->current_events & FD_CLOSE)
+    {
+      int r, errsv, buffer;
+
+      r = recv (socket->priv->fd, &buffer, sizeof (buffer), MSG_PEEK);
+      if (r < 0)
+          errsv = get_socket_errno ();
+
+      if (r > 0 ||
+          (r < 0 && errsv == WSAENOTCONN))
+        condition |= G_IO_IN;
+      else if (r == 0 ||
+               (r < 0 && (errsv == WSAESHUTDOWN || errsv == WSAECONNRESET ||
+                          errsv == WSAECONNABORTED || errsv == WSAENETRESET)))
+        condition |= G_IO_HUP;
+      else
+        condition |= G_IO_ERR;
+    }
+
+  if (socket->priv->closed)
     condition |= G_IO_HUP;
 
   /* Never report both G_IO_OUT and HUP, these are



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]