From 704a2ca02de0430786114e7d9bf7aa772c40b934 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Lureau?= Date: Fri, 10 Feb 2012 02:02:29 +0100 Subject: [PATCH] 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 file 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 -- 2.7.4