[glib] Always do async vs sync correctly in GSocketConnection streams



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]