mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 19:06:15 +01:00
Always do async vs sync correctly in GSocketConnection streams
Previously if a GSocketConnection had a blocking GSocket, it would sometimes block during asynchonous I/O, and if it had a non-blocking socket, it would sometimes return G_IO_ERROR_WOULD_BLOCK from synchronous I/O. This fixes the connection to not depend on the socket state. https://bugzilla.gnome.org/show_bug.cgi?id=616458
This commit is contained in:
parent
17fea2f749
commit
547311bfd8
@ -1716,9 +1716,11 @@ g_socket_check_connect_result
|
||||
g_socket_receive
|
||||
g_socket_receive_from
|
||||
g_socket_receive_message
|
||||
g_socket_receive_with_blocking
|
||||
g_socket_send
|
||||
g_socket_send_to
|
||||
g_socket_send_message
|
||||
g_socket_send_with_blocking
|
||||
g_socket_close
|
||||
g_socket_is_closed
|
||||
g_socket_shutdown
|
||||
|
@ -1271,9 +1271,11 @@ g_socket_new_from_fd
|
||||
g_socket_receive
|
||||
g_socket_receive_from
|
||||
g_socket_receive_message
|
||||
g_socket_receive_with_blocking
|
||||
g_socket_send
|
||||
g_socket_send_message
|
||||
g_socket_send_to
|
||||
g_socket_send_with_blocking
|
||||
g_socket_set_blocking
|
||||
g_socket_set_timeout
|
||||
g_socket_set_keepalive
|
||||
|
@ -1721,6 +1721,37 @@ g_socket_receive (GSocket *socket,
|
||||
gsize size,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return g_socket_receive_with_blocking (socket, buffer, size,
|
||||
socket->priv->blocking,
|
||||
cancellable, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_socket_receive_with_blocking:
|
||||
* @socket: a #GSocket
|
||||
* @buffer: a buffer to read data into (which should be at least @size
|
||||
* bytes long).
|
||||
* @size: the number of bytes you want to read from the socket
|
||||
* @blocking: whether to do blocking or non-blocking I/O
|
||||
* @cancellable: a %GCancellable or %NULL
|
||||
* @error: #GError for error reporting, or %NULL to ignore.
|
||||
*
|
||||
* This behaves exactly the same as g_socket_receive(), except that
|
||||
* the choice of blocking or non-blocking behavior is determined by
|
||||
* the @blocking argument rather than by @socket's properties.
|
||||
*
|
||||
* Returns: Number of bytes read, or -1 on error
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
gssize
|
||||
g_socket_receive_with_blocking (GSocket *socket,
|
||||
gchar *buffer,
|
||||
gsize size,
|
||||
gboolean blocking,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gssize ret;
|
||||
|
||||
@ -1734,7 +1765,7 @@ g_socket_receive (GSocket *socket,
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (socket->priv->blocking &&
|
||||
if (blocking &&
|
||||
!g_socket_condition_wait (socket,
|
||||
G_IO_IN, cancellable, error))
|
||||
return -1;
|
||||
@ -1746,7 +1777,7 @@ g_socket_receive (GSocket *socket,
|
||||
if (errsv == EINTR)
|
||||
continue;
|
||||
|
||||
if (socket->priv->blocking)
|
||||
if (blocking)
|
||||
{
|
||||
#ifdef WSAEWOULDBLOCK
|
||||
if (errsv == WSAEWOULDBLOCK)
|
||||
@ -1861,6 +1892,37 @@ g_socket_send (GSocket *socket,
|
||||
gsize size,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return g_socket_send_with_blocking (socket, buffer, size,
|
||||
socket->priv->blocking,
|
||||
cancellable, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_socket_send_with_blocking:
|
||||
* @socket: a #GSocket
|
||||
* @buffer: the buffer containing the data to send.
|
||||
* @size: the number of bytes to send
|
||||
* @blocking: whether to do blocking or non-blocking I/O
|
||||
* @cancellable: a %GCancellable or %NULL
|
||||
* @error: #GError for error reporting, or %NULL to ignore.
|
||||
*
|
||||
* This behaves exactly the same as g_socket_send(), except that
|
||||
* the choice of blocking or non-blocking behavior is determined by
|
||||
* the @blocking argument rather than by @socket's properties.
|
||||
*
|
||||
* Returns: Number of bytes written (which may be less than @size), or -1
|
||||
* on error
|
||||
*
|
||||
* Since: 2.26
|
||||
*/
|
||||
gssize
|
||||
g_socket_send_with_blocking (GSocket *socket,
|
||||
const gchar *buffer,
|
||||
gsize size,
|
||||
gboolean blocking,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gssize ret;
|
||||
|
||||
@ -1874,7 +1936,7 @@ g_socket_send (GSocket *socket,
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (socket->priv->blocking &&
|
||||
if (blocking &&
|
||||
!g_socket_condition_wait (socket,
|
||||
G_IO_OUT, cancellable, error))
|
||||
return -1;
|
||||
@ -1891,7 +1953,7 @@ g_socket_send (GSocket *socket,
|
||||
win32_unset_event_mask (socket, FD_WRITE);
|
||||
#endif
|
||||
|
||||
if (socket->priv->blocking)
|
||||
if (blocking)
|
||||
{
|
||||
#ifdef WSAEWOULDBLOCK
|
||||
if (errsv == WSAEWOULDBLOCK)
|
||||
|
@ -176,6 +176,19 @@ gboolean g_socket_speaks_ipv4 (GSocket
|
||||
GCredentials *g_socket_get_credentials (GSocket *socket,
|
||||
GError **error);
|
||||
|
||||
gssize g_socket_receive_with_blocking (GSocket *socket,
|
||||
gchar *buffer,
|
||||
gsize size,
|
||||
gboolean blocking,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gssize g_socket_send_with_blocking (GSocket *socket,
|
||||
const gchar *buffer,
|
||||
gsize size,
|
||||
gboolean blocking,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_SOCKET_H__ */
|
||||
|
@ -111,8 +111,9 @@ g_socket_input_stream_read (GInputStream *stream,
|
||||
{
|
||||
GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (stream);
|
||||
|
||||
return g_socket_receive (input_stream->priv->socket, buffer, count,
|
||||
cancellable, error);
|
||||
return g_socket_receive_with_blocking (input_stream->priv->socket,
|
||||
buffer, count, TRUE,
|
||||
cancellable, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -124,11 +125,12 @@ g_socket_input_stream_read_ready (GSocket *socket,
|
||||
GError *error = NULL;
|
||||
gssize result;
|
||||
|
||||
result = g_socket_receive (stream->priv->socket,
|
||||
stream->priv->buffer,
|
||||
stream->priv->count,
|
||||
stream->priv->cancellable,
|
||||
&error);
|
||||
result = g_socket_receive_with_blocking (stream->priv->socket,
|
||||
stream->priv->buffer,
|
||||
stream->priv->count,
|
||||
FALSE,
|
||||
stream->priv->cancellable,
|
||||
&error);
|
||||
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
|
||||
return TRUE;
|
||||
|
@ -113,8 +113,9 @@ g_socket_output_stream_write (GOutputStream *stream,
|
||||
{
|
||||
GSocketOutputStream *onput_stream = G_SOCKET_OUTPUT_STREAM (stream);
|
||||
|
||||
return g_socket_send (onput_stream->priv->socket, buffer, count,
|
||||
cancellable, error);
|
||||
return g_socket_send_with_blocking (onput_stream->priv->socket,
|
||||
buffer, count, TRUE,
|
||||
cancellable, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -126,11 +127,12 @@ g_socket_output_stream_write_ready (GSocket *socket,
|
||||
GError *error = NULL;
|
||||
gssize result;
|
||||
|
||||
result = g_socket_send (stream->priv->socket,
|
||||
stream->priv->buffer,
|
||||
stream->priv->count,
|
||||
stream->priv->cancellable,
|
||||
&error);
|
||||
result = g_socket_send_with_blocking (stream->priv->socket,
|
||||
stream->priv->buffer,
|
||||
stream->priv->count,
|
||||
FALSE,
|
||||
stream->priv->cancellable,
|
||||
&error);
|
||||
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
|
||||
return TRUE;
|
||||
|
Loading…
Reference in New Issue
Block a user