mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-27 12:42:10 +01:00
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
This commit is contained in:
parent
4f4714285d
commit
cf03e82478
147
gio/gsocket.c
147
gio/gsocket.c
@ -2230,31 +2230,31 @@ g_socket_accept (GSocket *socket,
|
|||||||
|
|
||||||
while (TRUE)
|
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)
|
if ((ret = accept (socket->priv->fd, NULL, 0)) < 0)
|
||||||
{
|
{
|
||||||
int errsv = get_socket_errno ();
|
int errsv = get_socket_errno ();
|
||||||
|
|
||||||
win32_unset_event_mask (socket, FD_ACCEPT);
|
|
||||||
|
|
||||||
if (errsv == EINTR)
|
if (errsv == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (socket->priv->blocking)
|
|
||||||
{
|
|
||||||
#ifdef WSAEWOULDBLOCK
|
#ifdef WSAEWOULDBLOCK
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
continue;
|
|
||||||
#else
|
#else
|
||||||
if (errsv == EWOULDBLOCK ||
|
if (errsv == EWOULDBLOCK ||
|
||||||
errsv == EAGAIN)
|
errsv == EAGAIN)
|
||||||
continue;
|
|
||||||
#endif
|
#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,
|
g_set_error (error, G_IO_ERROR,
|
||||||
socket_io_error_from_errno (errsv),
|
socket_io_error_from_errno (errsv),
|
||||||
@ -2368,6 +2368,8 @@ g_socket_connect (GSocket *socket,
|
|||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
win32_unset_event_mask (socket, FD_CONNECT);
|
||||||
|
|
||||||
if (socket->priv->blocking)
|
if (socket->priv->blocking)
|
||||||
{
|
{
|
||||||
if (g_socket_condition_wait (socket, G_IO_OUT, cancellable, error))
|
if (g_socket_condition_wait (socket, G_IO_OUT, cancellable, error))
|
||||||
@ -2602,11 +2604,6 @@ g_socket_receive_with_blocking (GSocket *socket,
|
|||||||
|
|
||||||
while (1)
|
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)
|
if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0)
|
||||||
{
|
{
|
||||||
int errsv = get_socket_errno ();
|
int errsv = get_socket_errno ();
|
||||||
@ -2614,17 +2611,24 @@ g_socket_receive_with_blocking (GSocket *socket,
|
|||||||
if (errsv == EINTR)
|
if (errsv == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (blocking)
|
|
||||||
{
|
|
||||||
#ifdef WSAEWOULDBLOCK
|
#ifdef WSAEWOULDBLOCK
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
continue;
|
|
||||||
#else
|
#else
|
||||||
if (errsv == EWOULDBLOCK ||
|
if (errsv == EWOULDBLOCK ||
|
||||||
errsv == EAGAIN)
|
errsv == EAGAIN)
|
||||||
continue;
|
|
||||||
#endif
|
#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);
|
win32_unset_event_mask (socket, FD_READ);
|
||||||
|
|
||||||
@ -2777,11 +2781,6 @@ g_socket_send_with_blocking (GSocket *socket,
|
|||||||
|
|
||||||
while (1)
|
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)
|
if ((ret = send (socket->priv->fd, buffer, size, G_SOCKET_DEFAULT_SEND_FLAGS)) < 0)
|
||||||
{
|
{
|
||||||
int errsv = get_socket_errno ();
|
int errsv = get_socket_errno ();
|
||||||
@ -2790,21 +2789,23 @@ g_socket_send_with_blocking (GSocket *socket,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef WSAEWOULDBLOCK
|
#ifdef WSAEWOULDBLOCK
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
win32_unset_event_mask (socket, FD_WRITE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (blocking)
|
|
||||||
{
|
|
||||||
#ifdef WSAEWOULDBLOCK
|
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
|
||||||
continue;
|
|
||||||
#else
|
#else
|
||||||
if (errsv == EWOULDBLOCK ||
|
if (errsv == EWOULDBLOCK ||
|
||||||
errsv == EAGAIN)
|
errsv == EAGAIN)
|
||||||
continue;
|
|
||||||
#endif
|
#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,
|
g_set_error (error, G_IO_ERROR,
|
||||||
socket_io_error_from_errno (errsv),
|
socket_io_error_from_errno (errsv),
|
||||||
@ -3874,11 +3875,6 @@ g_socket_send_message (GSocket *socket,
|
|||||||
|
|
||||||
while (1)
|
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);
|
result = sendmsg (socket->priv->fd, &msg, flags | G_SOCKET_DEFAULT_SEND_FLAGS);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
@ -3890,7 +3886,13 @@ g_socket_send_message (GSocket *socket,
|
|||||||
if (socket->priv->blocking &&
|
if (socket->priv->blocking &&
|
||||||
(errsv == EWOULDBLOCK ||
|
(errsv == EWOULDBLOCK ||
|
||||||
errsv == EAGAIN))
|
errsv == EAGAIN))
|
||||||
continue;
|
{
|
||||||
|
if (!g_socket_condition_wait (socket,
|
||||||
|
G_IO_OUT, cancellable, error))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
g_set_error (error, G_IO_ERROR,
|
||||||
socket_io_error_from_errno (errsv),
|
socket_io_error_from_errno (errsv),
|
||||||
@ -3942,11 +3944,6 @@ g_socket_send_message (GSocket *socket,
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (socket->priv->blocking &&
|
|
||||||
!g_socket_condition_wait (socket,
|
|
||||||
G_IO_OUT, cancellable, error))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (address)
|
if (address)
|
||||||
result = WSASendTo (socket->priv->fd,
|
result = WSASendTo (socket->priv->fd,
|
||||||
bufs, num_vectors,
|
bufs, num_vectors,
|
||||||
@ -3967,11 +3964,18 @@ g_socket_send_message (GSocket *socket,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
win32_unset_event_mask (socket, FD_WRITE);
|
{
|
||||||
|
win32_unset_event_mask (socket, FD_WRITE);
|
||||||
|
|
||||||
if (socket->priv->blocking &&
|
if (socket->priv->blocking)
|
||||||
errsv == WSAEWOULDBLOCK)
|
{
|
||||||
continue;
|
if (!g_socket_condition_wait (socket,
|
||||||
|
G_IO_OUT, cancellable, error))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
g_set_error (error, G_IO_ERROR,
|
||||||
socket_io_error_from_errno (errsv),
|
socket_io_error_from_errno (errsv),
|
||||||
@ -4634,11 +4638,6 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
/* do it */
|
/* do it */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (socket->priv->blocking &&
|
|
||||||
!g_socket_condition_wait (socket,
|
|
||||||
G_IO_IN, cancellable, error))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
addrlen = sizeof addr;
|
addrlen = sizeof addr;
|
||||||
if (address)
|
if (address)
|
||||||
result = WSARecvFrom (socket->priv->fd,
|
result = WSARecvFrom (socket->priv->fd,
|
||||||
@ -4658,11 +4657,19 @@ g_socket_receive_message (GSocket *socket,
|
|||||||
if (errsv == WSAEINTR)
|
if (errsv == WSAEINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
win32_unset_event_mask (socket, FD_READ);
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
|
{
|
||||||
|
win32_unset_event_mask (socket, FD_READ);
|
||||||
|
|
||||||
if (socket->priv->blocking &&
|
if (socket->priv->blocking)
|
||||||
errsv == WSAEWOULDBLOCK)
|
{
|
||||||
continue;
|
if (!g_socket_condition_wait (socket,
|
||||||
|
G_IO_IN, cancellable, error))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_set_error (error, G_IO_ERROR,
|
g_set_error (error, G_IO_ERROR,
|
||||||
socket_io_error_from_errno (errsv),
|
socket_io_error_from_errno (errsv),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user