mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-27 06:26: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
|
||||||
g_socket_receive_from
|
g_socket_receive_from
|
||||||
g_socket_receive_message
|
g_socket_receive_message
|
||||||
|
g_socket_receive_with_blocking
|
||||||
g_socket_send
|
g_socket_send
|
||||||
g_socket_send_to
|
g_socket_send_to
|
||||||
g_socket_send_message
|
g_socket_send_message
|
||||||
|
g_socket_send_with_blocking
|
||||||
g_socket_close
|
g_socket_close
|
||||||
g_socket_is_closed
|
g_socket_is_closed
|
||||||
g_socket_shutdown
|
g_socket_shutdown
|
||||||
|
@ -1271,9 +1271,11 @@ g_socket_new_from_fd
|
|||||||
g_socket_receive
|
g_socket_receive
|
||||||
g_socket_receive_from
|
g_socket_receive_from
|
||||||
g_socket_receive_message
|
g_socket_receive_message
|
||||||
|
g_socket_receive_with_blocking
|
||||||
g_socket_send
|
g_socket_send
|
||||||
g_socket_send_message
|
g_socket_send_message
|
||||||
g_socket_send_to
|
g_socket_send_to
|
||||||
|
g_socket_send_with_blocking
|
||||||
g_socket_set_blocking
|
g_socket_set_blocking
|
||||||
g_socket_set_timeout
|
g_socket_set_timeout
|
||||||
g_socket_set_keepalive
|
g_socket_set_keepalive
|
||||||
|
@ -1721,6 +1721,37 @@ g_socket_receive (GSocket *socket,
|
|||||||
gsize size,
|
gsize size,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
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;
|
gssize ret;
|
||||||
|
|
||||||
@ -1734,7 +1765,7 @@ g_socket_receive (GSocket *socket,
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (socket->priv->blocking &&
|
if (blocking &&
|
||||||
!g_socket_condition_wait (socket,
|
!g_socket_condition_wait (socket,
|
||||||
G_IO_IN, cancellable, error))
|
G_IO_IN, cancellable, error))
|
||||||
return -1;
|
return -1;
|
||||||
@ -1746,7 +1777,7 @@ g_socket_receive (GSocket *socket,
|
|||||||
if (errsv == EINTR)
|
if (errsv == EINTR)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (socket->priv->blocking)
|
if (blocking)
|
||||||
{
|
{
|
||||||
#ifdef WSAEWOULDBLOCK
|
#ifdef WSAEWOULDBLOCK
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
@ -1861,6 +1892,37 @@ g_socket_send (GSocket *socket,
|
|||||||
gsize size,
|
gsize size,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GError **error)
|
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;
|
gssize ret;
|
||||||
|
|
||||||
@ -1874,7 +1936,7 @@ g_socket_send (GSocket *socket,
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (socket->priv->blocking &&
|
if (blocking &&
|
||||||
!g_socket_condition_wait (socket,
|
!g_socket_condition_wait (socket,
|
||||||
G_IO_OUT, cancellable, error))
|
G_IO_OUT, cancellable, error))
|
||||||
return -1;
|
return -1;
|
||||||
@ -1891,7 +1953,7 @@ g_socket_send (GSocket *socket,
|
|||||||
win32_unset_event_mask (socket, FD_WRITE);
|
win32_unset_event_mask (socket, FD_WRITE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (socket->priv->blocking)
|
if (blocking)
|
||||||
{
|
{
|
||||||
#ifdef WSAEWOULDBLOCK
|
#ifdef WSAEWOULDBLOCK
|
||||||
if (errsv == WSAEWOULDBLOCK)
|
if (errsv == WSAEWOULDBLOCK)
|
||||||
|
@ -176,6 +176,19 @@ gboolean g_socket_speaks_ipv4 (GSocket
|
|||||||
GCredentials *g_socket_get_credentials (GSocket *socket,
|
GCredentials *g_socket_get_credentials (GSocket *socket,
|
||||||
GError **error);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __G_SOCKET_H__ */
|
#endif /* __G_SOCKET_H__ */
|
||||||
|
@ -111,7 +111,8 @@ g_socket_input_stream_read (GInputStream *stream,
|
|||||||
{
|
{
|
||||||
GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (stream);
|
GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (stream);
|
||||||
|
|
||||||
return g_socket_receive (input_stream->priv->socket, buffer, count,
|
return g_socket_receive_with_blocking (input_stream->priv->socket,
|
||||||
|
buffer, count, TRUE,
|
||||||
cancellable, error);
|
cancellable, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,9 +125,10 @@ g_socket_input_stream_read_ready (GSocket *socket,
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
gssize result;
|
gssize result;
|
||||||
|
|
||||||
result = g_socket_receive (stream->priv->socket,
|
result = g_socket_receive_with_blocking (stream->priv->socket,
|
||||||
stream->priv->buffer,
|
stream->priv->buffer,
|
||||||
stream->priv->count,
|
stream->priv->count,
|
||||||
|
FALSE,
|
||||||
stream->priv->cancellable,
|
stream->priv->cancellable,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
|
@ -113,7 +113,8 @@ g_socket_output_stream_write (GOutputStream *stream,
|
|||||||
{
|
{
|
||||||
GSocketOutputStream *onput_stream = G_SOCKET_OUTPUT_STREAM (stream);
|
GSocketOutputStream *onput_stream = G_SOCKET_OUTPUT_STREAM (stream);
|
||||||
|
|
||||||
return g_socket_send (onput_stream->priv->socket, buffer, count,
|
return g_socket_send_with_blocking (onput_stream->priv->socket,
|
||||||
|
buffer, count, TRUE,
|
||||||
cancellable, error);
|
cancellable, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,9 +127,10 @@ g_socket_output_stream_write_ready (GSocket *socket,
|
|||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
gssize result;
|
gssize result;
|
||||||
|
|
||||||
result = g_socket_send (stream->priv->socket,
|
result = g_socket_send_with_blocking (stream->priv->socket,
|
||||||
stream->priv->buffer,
|
stream->priv->buffer,
|
||||||
stream->priv->count,
|
stream->priv->count,
|
||||||
|
FALSE,
|
||||||
stream->priv->cancellable,
|
stream->priv->cancellable,
|
||||||
&error);
|
&error);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user