glib2: fix hang on gsocket

This commit is contained in:
Ignacio Casal Quinteiro
2014-12-23 08:41:13 +01:00
parent d7810c7f7e
commit 2131facaab
2 changed files with 280 additions and 3 deletions

View File

@@ -0,0 +1,274 @@
From 177ff38e103a76b7cd153c4c8014159eb6a9eb60 Mon Sep 17 00:00:00 2001
From: Ignacio Casal Quinteiro <icq@gnome.org>
Date: Mon, 22 Dec 2014 16:38:50 +0100
Subject: [PATCH] gsocket: block when errno says it will block
On windows it may happen we recreate a gsocket
out of a fd from another gsocket that already
got the FD_WRITE event. If this happens in order
to get another FD_WRITE we need to have tried an
operation that might need such event. What we do
here is to first try to do the operation and
then if errno specifies that we might block then
wait for that event to occur.
https://bugzilla.gnome.org/show_bug.cgi?id=741707
---
gio/gsocket.c | 147 ++++++++++++++++++++++++++++++----------------------------
1 file changed, 77 insertions(+), 70 deletions(-)
diff --git a/gio/gsocket.c b/gio/gsocket.c
index d9e135d..f144674 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -2230,31 +2230,31 @@ g_socket_accept (GSocket *socket,
while (TRUE)
{
- if (socket->priv->blocking &&
- !g_socket_condition_wait (socket,
- G_IO_IN, cancellable, error))
- return NULL;
-
if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
{
int errsv = get_socket_errno ();
- win32_unset_event_mask (socket, FD_ACCEPT);
-
if (errsv == EINTR)
continue;
- if (socket->priv->blocking)
- {
#ifdef WSAEWOULDBLOCK
- if (errsv == WSAEWOULDBLOCK)
- continue;
+ if (errsv == WSAEWOULDBLOCK)
#else
- if (errsv == EWOULDBLOCK ||
- errsv == EAGAIN)
- continue;
+ if (errsv == EWOULDBLOCK ||
+ errsv == EAGAIN)
#endif
- }
+ {
+ win32_unset_event_mask (socket, FD_ACCEPT);
+
+ if (socket->priv->blocking)
+ {
+ if (!g_socket_condition_wait (socket,
+ G_IO_IN, cancellable, error))
+ return NULL;
+
+ continue;
+ }
+ }
g_set_error (error, G_IO_ERROR,
socket_io_error_from_errno (errsv),
@@ -2368,6 +2368,8 @@ g_socket_connect (GSocket *socket,
if (errsv == WSAEWOULDBLOCK)
#endif
{
+ win32_unset_event_mask (socket, FD_CONNECT);
+
if (socket->priv->blocking)
{
if (g_socket_condition_wait (socket, G_IO_OUT, cancellable, error))
@@ -2602,11 +2604,6 @@ g_socket_receive_with_blocking (GSocket *socket,
while (1)
{
- if (blocking &&
- !g_socket_condition_wait (socket,
- G_IO_IN, cancellable, error))
- return -1;
-
if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0)
{
int errsv = get_socket_errno ();
@@ -2614,17 +2611,24 @@ g_socket_receive_with_blocking (GSocket *socket,
if (errsv == EINTR)
continue;
- if (blocking)
- {
#ifdef WSAEWOULDBLOCK
- if (errsv == WSAEWOULDBLOCK)
- continue;
+ if (errsv == WSAEWOULDBLOCK)
#else
- if (errsv == EWOULDBLOCK ||
- errsv == EAGAIN)
- continue;
+ if (errsv == EWOULDBLOCK ||
+ errsv == EAGAIN)
#endif
- }
+ {
+ win32_unset_event_mask (socket, FD_READ);
+
+ if (blocking)
+ {
+ if (!g_socket_condition_wait (socket,
+ G_IO_IN, cancellable, error))
+ return -1;
+
+ continue;
+ }
+ }
win32_unset_event_mask (socket, FD_READ);
@@ -2777,11 +2781,6 @@ g_socket_send_with_blocking (GSocket *socket,
while (1)
{
- if (blocking &&
- !g_socket_condition_wait (socket,
- G_IO_OUT, cancellable, error))
- return -1;
-
if ((ret = send (socket->priv->fd, buffer, size, G_SOCKET_DEFAULT_SEND_FLAGS)) < 0)
{
int errsv = get_socket_errno ();
@@ -2790,21 +2789,23 @@ g_socket_send_with_blocking (GSocket *socket,
continue;
#ifdef WSAEWOULDBLOCK
- if (errsv == WSAEWOULDBLOCK)
- win32_unset_event_mask (socket, FD_WRITE);
-#endif
-
- if (blocking)
- {
-#ifdef WSAEWOULDBLOCK
- if (errsv == WSAEWOULDBLOCK)
- continue;
+ if (errsv == WSAEWOULDBLOCK)
#else
- if (errsv == EWOULDBLOCK ||
- errsv == EAGAIN)
- continue;
+ if (errsv == EWOULDBLOCK ||
+ errsv == EAGAIN)
#endif
- }
+ {
+ win32_unset_event_mask (socket, FD_WRITE);
+
+ if (blocking)
+ {
+ if (!g_socket_condition_wait (socket,
+ G_IO_OUT, cancellable, error))
+ return -1;
+
+ continue;
+ }
+ }
g_set_error (error, G_IO_ERROR,
socket_io_error_from_errno (errsv),
@@ -3874,11 +3875,6 @@ g_socket_send_message (GSocket *socket,
while (1)
{
- if (socket->priv->blocking &&
- !g_socket_condition_wait (socket,
- G_IO_OUT, cancellable, error))
- return -1;
-
result = sendmsg (socket->priv->fd, &msg, flags | G_SOCKET_DEFAULT_SEND_FLAGS);
if (result < 0)
{
@@ -3890,7 +3886,13 @@ g_socket_send_message (GSocket *socket,
if (socket->priv->blocking &&
(errsv == EWOULDBLOCK ||
errsv == EAGAIN))
- continue;
+ {
+ if (!g_socket_condition_wait (socket,
+ G_IO_OUT, cancellable, error))
+ return -1;
+
+ continue;
+ }
g_set_error (error, G_IO_ERROR,
socket_io_error_from_errno (errsv),
@@ -3942,11 +3944,6 @@ g_socket_send_message (GSocket *socket,
while (1)
{
- if (socket->priv->blocking &&
- !g_socket_condition_wait (socket,
- G_IO_OUT, cancellable, error))
- return -1;
-
if (address)
result = WSASendTo (socket->priv->fd,
bufs, num_vectors,
@@ -3967,11 +3964,18 @@ g_socket_send_message (GSocket *socket,
continue;
if (errsv == WSAEWOULDBLOCK)
- win32_unset_event_mask (socket, FD_WRITE);
+ {
+ win32_unset_event_mask (socket, FD_WRITE);
- if (socket->priv->blocking &&
- errsv == WSAEWOULDBLOCK)
- continue;
+ if (socket->priv->blocking)
+ {
+ if (!g_socket_condition_wait (socket,
+ G_IO_OUT, cancellable, error))
+ return -1;
+
+ continue;
+ }
+ }
g_set_error (error, G_IO_ERROR,
socket_io_error_from_errno (errsv),
@@ -4634,11 +4638,6 @@ g_socket_receive_message (GSocket *socket,
/* do it */
while (1)
{
- if (socket->priv->blocking &&
- !g_socket_condition_wait (socket,
- G_IO_IN, cancellable, error))
- return -1;
-
addrlen = sizeof addr;
if (address)
result = WSARecvFrom (socket->priv->fd,
@@ -4658,11 +4657,19 @@ g_socket_receive_message (GSocket *socket,
if (errsv == WSAEINTR)
continue;
- win32_unset_event_mask (socket, FD_READ);
+ if (errsv == WSAEWOULDBLOCK)
+ {
+ win32_unset_event_mask (socket, FD_READ);
- if (socket->priv->blocking &&
- errsv == WSAEWOULDBLOCK)
- continue;
+ if (socket->priv->blocking)
+ {
+ if (!g_socket_condition_wait (socket,
+ G_IO_IN, cancellable, error))
+ return -1;
+
+ continue;
+ }
+ }
g_set_error (error, G_IO_ERROR,
socket_io_error_from_errno (errsv),
--
2.1.0

View File

@@ -3,7 +3,7 @@
_realname=glib2
pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}"
pkgver=2.42.1
pkgrel=1
pkgrel=2
url="http://www.gtk.org/"
arch=('any')
pkgdesc="Common C routines used by GTK+ 2.4 and other libs (mingw-w64)"
@@ -25,7 +25,8 @@ source=("http://ftp.gnome.org/pub/GNOME/sources/glib/${pkgver%.*}/glib-$pkgver.t
0021-use-64bit-stat-for-localfile-size-calc.all.patch
0023-print-in-binary-more-for-testing.all.patch
0024-return-actually-written-data-in-printf.all.patch
0026-define-HAVE_IF_NAMETOINDEX.patch)
0026-define-HAVE_IF_NAMETOINDEX.patch
0001-gsocket-block-when-errno-says-it-will-block.patch)
md5sums=('89c4119e50e767d3532158605ee9121a'
'98c7778b5e8a30dbcdb86bcd15f9c11d'
'6eb9d56028ea3bbec3d053254a00a04b'
@@ -36,7 +37,8 @@ md5sums=('89c4119e50e767d3532158605ee9121a'
'952989e534235721d30b9ee3d89cc225'
'217a997ede1b93ac06f96ed869b74378'
'500f39baea98d98e4a2f877ad56f55a5'
'de51a19cc5bfd0d54a59e9ac36cbafa2')
'de51a19cc5bfd0d54a59e9ac36cbafa2'
'c8942cf5035f97ade5ab9c757a210f01')
prepare() {
cd "$srcdir/glib-$pkgver"
@@ -50,6 +52,7 @@ prepare() {
patch -Np1 -i "$srcdir/0021-use-64bit-stat-for-localfile-size-calc.all.patch"
patch -Np1 -i "$srcdir/0023-print-in-binary-more-for-testing.all.patch"
patch -Np1 -i "$srcdir/0024-return-actually-written-data-in-printf.all.patch"
patch -Np1 -i "$srcdir/0001-gsocket-block-when-errno-says-it-will-block.patch"
NOCONFIGURE=1 ./autogen.sh