[glib] Always do async vs sync correctly in GSocketConnection streams
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] Always do async vs sync correctly in GSocketConnection streams
- Date: Sun, 15 Aug 2010 19:35:44 +0000 (UTC)
commit 547311bfd8661e25e588e1f434f15c5f2f32c3a7
Author: Dan Winship <danw gnome org>
Date: Thu Jun 24 13:09:14 2010 -0400
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
docs/reference/gio/gio-sections.txt | 2 +
gio/gio.symbols | 2 +
gio/gsocket.c | 70 +++++++++++++++++++++++++++++++++--
gio/gsocket.h | 13 ++++++
gio/gsocketinputstream.c | 16 ++++---
gio/gsocketoutputstream.c | 16 ++++---
6 files changed, 101 insertions(+), 18 deletions(-)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 7ed6cfd..cd23dea 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -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
diff --git a/gio/gio.symbols b/gio/gio.symbols
index 68ea6d4..eb23edd 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -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
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 3a26a7d..880ba38 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -1722,6 +1722,37 @@ g_socket_receive (GSocket *socket,
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;
g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
@@ -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)
@@ -1862,6 +1893,37 @@ g_socket_send (GSocket *socket,
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;
g_return_val_if_fail (G_IS_SOCKET (socket) && buffer != NULL, FALSE);
@@ -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)
diff --git a/gio/gsocket.h b/gio/gsocket.h
index b2476cc..d17de32 100644
--- a/gio/gsocket.h
+++ b/gio/gsocket.h
@@ -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__ */
diff --git a/gio/gsocketinputstream.c b/gio/gsocketinputstream.c
index 4b26ed4..07c4740 100644
--- a/gio/gsocketinputstream.c
+++ b/gio/gsocketinputstream.c
@@ -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;
diff --git a/gio/gsocketoutputstream.c b/gio/gsocketoutputstream.c
index e79e261..b5d9412 100644
--- a/gio/gsocketoutputstream.c
+++ b/gio/gsocketoutputstream.c
@@ -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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]