[glib] gsocket: always try before waiting for condition
- From: Paolo Borelli <pborelli src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] gsocket: always try before waiting for condition
- Date: Sat, 17 Jan 2015 14:05:44 +0000 (UTC)
commit cf03e824780d4ca58de664737bf5ba9ed416cfa2
Author: Ignacio Casal Quinteiro <icq gnome org>
Date: Mon Dec 22 16:38:50 2014 +0100
gsocket: always try before waiting for condition
When implementing blocking operations on top of
nonblocking sockets we should always first try to
perform the operation and then if needed handle
EAGAIN and wait with g_socket_wait_condition.
This is an optimization since we avoid calling
wait condition when it is not needed, but most
importantly this fixes hangs on win32 where some
events (in particular FD_WRITE) are only emitted
after the operation fails with EWOULDBLOCK.
https://bugzilla.gnome.org/show_bug.cgi?id=732439
https://bugzilla.gnome.org/show_bug.cgi?id=741707
gio/gsocket.c | 147 ++++++++++++++++++++++++++++++---------------------------
1 files 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),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]