diff options
author | Dan Winship <danw@gnome.org> | 2009-06-23 17:42:01 -0400 |
---|---|---|
committer | Dan Winship <danw@gnome.org> | 2009-06-30 11:42:17 -0400 |
commit | 53beca955e016fb9ef4e80d223d059bc5e51dd41 (patch) | |
tree | 1a7b5f107f53ce2ad3da5b3615917d0f02ec630e | |
parent | fc2b3ee560e29b4ef6e70928b0be75d833d75aec (diff) |
Add GCancellables to GSocket ops
Currently, to implement cancellability correctly, all synchronous
calls to GSocket must be preceded by a g_socket_condition_wait() call,
(even though GSocket does this internally as well) and all
asynchronous calls must do occasional manual
g_cancellable_is_cancelled() checks. Since it's trivial to do these
checks inside GSocket instead, and we don't particularly want to
encourage people to use the APIs non-cancellably, move the
cancellation support into GSocket and simplify the existing callers.
http://bugzilla.gnome.org/show_bug.cgi?id=586797
-rw-r--r-- | gio/gsocket.c | 74 | ||||
-rw-r--r-- | gio/gsocket.h | 8 | ||||
-rw-r--r-- | gio/gsocketclient.c | 4 | ||||
-rw-r--r-- | gio/gsocketinputstream.c | 27 | ||||
-rw-r--r-- | gio/gsocketlistener.c | 32 | ||||
-rw-r--r-- | gio/gsocketoutputstream.c | 27 | ||||
-rw-r--r-- | gio/gtcpconnection.c | 21 | ||||
-rw-r--r-- | gio/gunixconnection.c | 8 | ||||
-rw-r--r-- | gio/tests/socket-client.c | 14 | ||||
-rw-r--r-- | gio/tests/socket-server.c | 13 |
10 files changed, 119 insertions, 109 deletions
diff --git a/gio/gsocket.c b/gio/gsocket.c index 151adb5d9..3f92c7573 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -1332,6 +1332,7 @@ g_socket_speaks_ipv4 (GSocket *socket) /** * g_socket_accept: * @socket: a #GSocket. + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Accept incoming connections on a connection-based socket. This removes @@ -1352,6 +1353,7 @@ g_socket_speaks_ipv4 (GSocket *socket) */ GSocket * g_socket_accept (GSocket *socket, + GCancellable *cancellable, GError **error) { GSocket *new_socket; @@ -1366,7 +1368,7 @@ g_socket_accept (GSocket *socket, { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_IN, NULL, error)) + G_IO_IN, cancellable, error)) return NULL; if ((ret = accept (socket->priv->fd, NULL, 0)) < 0) @@ -1442,6 +1444,7 @@ g_socket_accept (GSocket *socket, * g_socket_connect: * @socket: a #GSocket. * @address: a #GSocketAddress specifying the remote address. + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Connect the socket to the specified remote address. @@ -1468,6 +1471,7 @@ g_socket_accept (GSocket *socket, gboolean g_socket_connect (GSocket *socket, GSocketAddress *address, + GCancellable *cancellable, GError **error) { struct sockaddr_storage buffer; @@ -1498,11 +1502,12 @@ g_socket_connect (GSocket *socket, { if (socket->priv->blocking) { - g_socket_condition_wait (socket, G_IO_OUT, NULL, NULL); - if (g_socket_check_connect_result (socket, error)) - break; - else - g_prefix_error (error, _("Error connecting: ")); + if (g_socket_condition_wait (socket, G_IO_OUT, cancellable, error)) + { + if (g_socket_check_connect_result (socket, error)) + break; + } + g_prefix_error (error, _("Error connecting: ")); } else g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING, @@ -1570,6 +1575,7 @@ g_socket_check_connect_result (GSocket *socket, * @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 + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Receive data (up to @size bytes) from a socket. This is mainly used by @@ -1600,10 +1606,11 @@ g_socket_check_connect_result (GSocket *socket, * Since: 2.22 */ gssize -g_socket_receive (GSocket *socket, - gchar *buffer, - gsize size, - GError **error) +g_socket_receive (GSocket *socket, + gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error) { gssize ret; @@ -1612,11 +1619,14 @@ g_socket_receive (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return -1; + while (1) { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_IN, NULL, error)) + G_IO_IN, cancellable, error)) return -1; if ((ret = recv (socket->priv->fd, buffer, size, 0)) < 0) @@ -1661,6 +1671,7 @@ g_socket_receive (GSocket *socket, * @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 + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Receive data (up to @size bytes) from a socket. @@ -1680,6 +1691,7 @@ g_socket_receive_from (GSocket *socket, GSocketAddress **address, gchar *buffer, gsize size, + GCancellable *cancellable, GError **error) { GInputVector v; @@ -1691,6 +1703,7 @@ g_socket_receive_from (GSocket *socket, address, &v, 1, NULL, 0, NULL, + cancellable, error); } @@ -1699,6 +1712,7 @@ g_socket_receive_from (GSocket *socket, * @socket: a #GSocket * @buffer: the buffer containing the data to send. * @size: the number of bytes to send + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Tries to send @size bytes from @buffer on the socket. This is @@ -1722,10 +1736,11 @@ g_socket_receive_from (GSocket *socket, * Since: 2.22 */ gssize -g_socket_send (GSocket *socket, - const gchar *buffer, - gsize size, - GError **error) +g_socket_send (GSocket *socket, + const gchar *buffer, + gsize size, + GCancellable *cancellable, + GError **error) { gssize ret; @@ -1734,11 +1749,14 @@ g_socket_send (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return -1; + while (1) { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_OUT, NULL, error)) + G_IO_OUT, cancellable, error)) return -1; if ((ret = send (socket->priv->fd, buffer, size, 0)) < 0) @@ -1782,6 +1800,7 @@ g_socket_send (GSocket *socket, * @address: a #GSocketAddress, or %NULL * @buffer: the buffer containing the data to send. * @size: the number of bytes to send + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Tries to send @size bytes from @buffer to @address. If @address is @@ -1800,6 +1819,7 @@ g_socket_send_to (GSocket *socket, GSocketAddress *address, const gchar *buffer, gsize size, + GCancellable *cancellable, GError **error) { GOutputVector v; @@ -1811,7 +1831,9 @@ g_socket_send_to (GSocket *socket, address, &v, 1, NULL, 0, - 0, error); + 0, + cancellable, + error); } /** @@ -2491,6 +2513,7 @@ g_socket_condition_wait (GSocket *socket, * %NULL. * @num_messages: number of elements in @messages, or -1. * @flags: an int containing #GSocketMsgFlags flags + * @cancellable: a %GCancellable or %NULL * @error: #GError for error reporting, or %NULL to ignore. * * Send data to @address on @socket. This is the most complicated and @@ -2544,6 +2567,7 @@ g_socket_send_message (GSocket *socket, GSocketControlMessage **messages, gint num_messages, gint flags, + GCancellable *cancellable, GError **error) { GOutputVector one_vector; @@ -2552,6 +2576,9 @@ g_socket_send_message (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return -1; + if (num_vectors == -1) { for (num_vectors = 0; @@ -2650,7 +2677,7 @@ g_socket_send_message (GSocket *socket, { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_OUT, NULL, error)) + G_IO_OUT, cancellable, error)) return -1; result = sendmsg (socket->priv->fd, &msg, flags); @@ -2718,7 +2745,7 @@ g_socket_send_message (GSocket *socket, { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_OUT, NULL, error)) + G_IO_OUT, cancellable, error)) return -1; if (address) @@ -2772,6 +2799,7 @@ g_socket_send_message (GSocket *socket, * @num_messages: a pointer which will be filled with the number of * elements in @messages, or %NULL * @flags: a pointer to an int containing #GSocketMsgFlags flags + * @cancellable: a %GCancellable or %NULL * @error: a #GError pointer, or %NULL * * Receive data from a socket. This is the most complicated and @@ -2842,6 +2870,7 @@ g_socket_receive_message (GSocket *socket, GSocketControlMessage ***messages, gint *num_messages, gint *flags, + GCancellable *cancellable, GError **error) { GInputVector one_vector; @@ -2850,6 +2879,9 @@ g_socket_receive_message (GSocket *socket, if (!check_socket (socket, error)) return -1; + if (g_cancellable_set_error_if_cancelled (cancellable, error)) + return -1; + if (num_vectors == -1) { for (num_vectors = 0; @@ -2927,7 +2959,7 @@ g_socket_receive_message (GSocket *socket, { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_IN, NULL, error)) + G_IO_IN, cancellable, error)) return -1; result = recvmsg (socket->priv->fd, &msg, msg.msg_flags); @@ -3055,7 +3087,7 @@ g_socket_receive_message (GSocket *socket, { if (socket->priv->blocking && !g_socket_condition_wait (socket, - G_IO_IN, NULL, error)) + G_IO_IN, cancellable, error)) return -1; addrlen = sizeof addr; diff --git a/gio/gsocket.h b/gio/gsocket.h index 05d5d37fd..c56a14c80 100644 --- a/gio/gsocket.h +++ b/gio/gsocket.h @@ -104,6 +104,7 @@ gboolean g_socket_bind (GSocket GError **error); gboolean g_socket_connect (GSocket *socket, GSocketAddress *address, + GCancellable *cancellable, GError **error); gboolean g_socket_check_connect_result (GSocket *socket, GError **error); @@ -114,26 +115,31 @@ gboolean g_socket_condition_wait (GSocket GCancellable *cancellable, GError **error); GSocket * g_socket_accept (GSocket *socket, + GCancellable *cancellable, GError **error); gboolean g_socket_listen (GSocket *socket, GError **error); gssize g_socket_receive (GSocket *socket, gchar *buffer, gsize size, + GCancellable *cancellable, GError **error); gssize g_socket_receive_from (GSocket *socket, GSocketAddress **address, gchar *buffer, gsize size, + GCancellable *cancellable, GError **error); gssize g_socket_send (GSocket *socket, const gchar *buffer, gsize size, + GCancellable *cancellable, GError **error); gssize g_socket_send_to (GSocket *socket, GSocketAddress *address, const gchar *buffer, gsize size, + GCancellable *cancellable, GError **error); gssize g_socket_receive_message (GSocket *socket, GSocketAddress **address, @@ -142,6 +148,7 @@ gssize g_socket_receive_message (GSocket GSocketControlMessage ***messages, gint *num_messages, gint *flags, + GCancellable *cancellable, GError **error); gssize g_socket_send_message (GSocket *socket, GSocketAddress *address, @@ -150,6 +157,7 @@ gssize g_socket_send_message (GSocket GSocketControlMessage **messages, gint num_messages, gint flags, + GCancellable *cancellable, GError **error); gboolean g_socket_close (GSocket *socket, GError **error); diff --git a/gio/gsocketclient.c b/gio/gsocketclient.c index 3bbdb977a..cfb398f96 100644 --- a/gio/gsocketclient.c +++ b/gio/gsocketclient.c @@ -528,7 +528,7 @@ g_socket_client_connect (GSocketClient *client, socket = create_socket (client, address, &last_error); if (socket != NULL) { - if (g_socket_connect (socket, address, &last_error)) + if (g_socket_connect (socket, address, cancellable, &last_error)) connection = g_socket_connection_factory_create_connection (socket); g_object_unref (socket); @@ -776,7 +776,7 @@ g_socket_client_enumerator_callback (GObject *object, if (socket != NULL) { g_socket_set_blocking (socket, FALSE); - if (g_socket_connect (socket, address, &tmp_error)) + if (g_socket_connect (socket, address, data->cancellable, &tmp_error)) { data->current_socket = socket; g_socket_client_async_connect_complete (data); diff --git a/gio/gsocketinputstream.c b/gio/gsocketinputstream.c index 6c0c68a4a..d1fdbc3b8 100644 --- a/gio/gsocketinputstream.c +++ b/gio/gsocketinputstream.c @@ -112,11 +112,8 @@ g_socket_input_stream_read (GInputStream *stream, { GSocketInputStream *input_stream = G_SOCKET_INPUT_STREAM (stream); - if (!g_socket_condition_wait (input_stream->priv->socket, - G_IO_IN, cancellable, error)) - return -1; - - return g_socket_receive (input_stream->priv->socket, buffer, count, error); + return g_socket_receive (input_stream->priv->socket, buffer, count, + cancellable, error); } static gboolean @@ -126,22 +123,18 @@ g_socket_input_stream_read_ready (GSocket *socket, { GSimpleAsyncResult *simple; GError *error = NULL; + gssize result; simple = stream->priv->result; stream->priv->result = NULL; - if (!g_cancellable_set_error_if_cancelled (stream->priv->cancellable, - &error)) - { - gssize result; - - result = g_socket_receive (stream->priv->socket, - stream->priv->buffer, - stream->priv->count, - &error); - if (result >= 0) - g_simple_async_result_set_op_res_gssize (simple, result); - } + result = g_socket_receive (stream->priv->socket, + stream->priv->buffer, + stream->priv->count, + stream->priv->cancellable, + &error); + if (result >= 0) + g_simple_async_result_set_op_res_gssize (simple, result); if (error) { diff --git a/gio/gsocketlistener.c b/gio/gsocketlistener.c index fd9f98c8a..f668d1496 100644 --- a/gio/gsocketlistener.c +++ b/gio/gsocketlistener.c @@ -628,7 +628,7 @@ g_socket_listener_accept_socket (GSocketListener *listener, g_main_loop_unref (loop); } - if (!(socket = g_socket_accept (accept_socket, error))) + if (!(socket = g_socket_accept (accept_socket, cancellable, error))) return NULL; if (source_object) @@ -695,27 +695,21 @@ accept_ready (GSocket *accept_socket, { struct AcceptAsyncData *data = _data; GError *error = NULL; + GSocket *socket; + GObject *source_object; - if (!g_cancellable_set_error_if_cancelled (data->cancellable, - &error)) + socket = g_socket_accept (accept_socket, data->cancellable, &error); + if (socket) { - GSocket *socket; - GObject *source_object; - - socket = g_socket_accept (accept_socket, &error); - if (socket) - { - g_simple_async_result_set_op_res_gpointer (data->simple, socket, - g_object_unref); - source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark); - if (source_object) - g_object_set_qdata_full (G_OBJECT (data->simple), - source_quark, - g_object_ref (source_object), g_object_unref); - } + g_simple_async_result_set_op_res_gpointer (data->simple, socket, + g_object_unref); + source_object = g_object_get_qdata (G_OBJECT (accept_socket), source_quark); + if (source_object) + g_object_set_qdata_full (G_OBJECT (data->simple), + source_quark, + g_object_ref (source_object), g_object_unref); } - - if (error) + else { g_simple_async_result_set_from_error (data->simple, error); g_error_free (error); diff --git a/gio/gsocketoutputstream.c b/gio/gsocketoutputstream.c index 98d5c474e..121fb95e1 100644 --- a/gio/gsocketoutputstream.c +++ b/gio/gsocketoutputstream.c @@ -114,11 +114,8 @@ g_socket_output_stream_write (GOutputStream *stream, { GSocketOutputStream *onput_stream = G_SOCKET_OUTPUT_STREAM (stream); - if (!g_socket_condition_wait (onput_stream->priv->socket, - G_IO_OUT, cancellable, error)) - return -1; - - return g_socket_send (onput_stream->priv->socket, buffer, count, error); + return g_socket_send (onput_stream->priv->socket, buffer, count, + cancellable, error); } static gboolean @@ -128,22 +125,18 @@ g_socket_output_stream_write_ready (GSocket *socket, { GSimpleAsyncResult *simple; GError *error = NULL; + gssize result; simple = stream->priv->result; stream->priv->result = NULL; - if (!g_cancellable_set_error_if_cancelled (stream->priv->cancellable, - &error)) - { - gssize result; - - result = g_socket_send (stream->priv->socket, - stream->priv->buffer, - stream->priv->count, - &error); - if (result >= 0) - g_simple_async_result_set_op_res_gssize (simple, result); - } + result = g_socket_send (stream->priv->socket, + stream->priv->buffer, + stream->priv->count, + stream->priv->cancellable, + &error); + if (result >= 0) + g_simple_async_result_set_op_res_gssize (simple, result); if (error) { diff --git a/gio/gtcpconnection.c b/gio/gtcpconnection.c index 738ccb019..611c19525 100644 --- a/gio/gtcpconnection.c +++ b/gio/gtcpconnection.c @@ -175,17 +175,9 @@ g_tcp_connection_close (GIOStream *stream, { while (TRUE) { - if (!g_socket_condition_wait (socket, - G_IO_IN, cancellable, error)) - { - had_error = TRUE; - error = NULL; - break; - } - my_error = NULL; ret = g_socket_receive (socket, buffer, sizeof (buffer), - &my_error); + cancellable, &my_error); if (ret < 0) { if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) @@ -265,15 +257,8 @@ close_read_ready (GSocket *socket, char buffer[1024]; gssize ret; - if (g_cancellable_set_error_if_cancelled (data->cancellable, - &error)) - { - async_close_finish (data, error, TRUE); - g_error_free (error); - return FALSE; - } - - ret = g_socket_receive (socket, buffer, sizeof (buffer), &error); + ret = g_socket_receive (socket, buffer, sizeof (buffer), + data->cancellable, &error); if (ret < 0) { if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) diff --git a/gio/gunixconnection.c b/gio/gunixconnection.c index 0911ff042..92ad246f8 100644 --- a/gio/gunixconnection.c +++ b/gio/gunixconnection.c @@ -86,8 +86,7 @@ g_unix_connection_send_fd (GUnixConnection *connection, } g_object_get (connection, "socket", &socket, NULL); - if (!g_socket_condition_wait (socket, G_IO_OUT, cancellable, error) || - g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, error) != 1) + if (g_socket_send_message (socket, NULL, NULL, 0, &scm, 1, 0, cancellable, error) != 1) /* XXX could it 'fail' with zero? */ { g_object_unref (socket); @@ -133,9 +132,8 @@ g_unix_connection_receive_fd (GUnixConnection *connection, g_return_val_if_fail (G_IS_UNIX_CONNECTION (connection), -1); g_object_get (connection, "socket", &socket, NULL); - if (!g_socket_condition_wait (socket, G_IO_IN, cancellable, error) || - g_socket_receive_message (socket, NULL, NULL, 0, - &scms, &nscm, NULL, error) != 1) + if (g_socket_receive_message (socket, NULL, NULL, 0, + &scms, &nscm, NULL, cancellable, error) != 1) /* XXX it _could_ 'fail' with zero. */ { g_object_unref (socket); diff --git a/gio/tests/socket-client.c b/gio/tests/socket-client.c index abc28af56..8409a5fd4 100644 --- a/gio/tests/socket-client.c +++ b/gio/tests/socket-client.c @@ -172,7 +172,7 @@ main (int argc, return 1; } - if (g_socket_connect (socket, address, &error)) + if (g_socket_connect (socket, address, cancellable, &error)) break; g_printerr ("%s: Connection to %s failed: %s, trying next\n", argv[0], socket_address_to_string (address), error->message); g_error_free (error); @@ -215,9 +215,11 @@ main (int argc, ensure_condition (socket, "send", cancellable, G_IO_OUT); if (use_udp) size = g_socket_send_to (socket, address, - buffer, to_send, &error); + buffer, to_send, + cancellable, &error); else - size = g_socket_send (socket, buffer, to_send, &error); + size = g_socket_send (socket, buffer, to_send, + cancellable, &error); if (size < 0) { @@ -252,9 +254,11 @@ main (int argc, ensure_condition (socket, "receive", cancellable, G_IO_IN); if (use_udp) size = g_socket_receive_from (socket, &src_address, - buffer, sizeof buffer, &error); + buffer, sizeof buffer, + cancellable, &error); else - size = g_socket_receive (socket, buffer, sizeof buffer, &error); + size = g_socket_receive (socket, buffer, sizeof buffer, + cancellable, &error); if (size < 0) { diff --git a/gio/tests/socket-server.c b/gio/tests/socket-server.c index 231d5c98c..b98c696e4 100644 --- a/gio/tests/socket-server.c +++ b/gio/tests/socket-server.c @@ -170,7 +170,7 @@ main (int argc, g_print ("listening on port %d...\n", port); ensure_condition (socket, "accept", cancellable, G_IO_IN); - new_socket = g_socket_accept (socket, &error); + new_socket = g_socket_accept (socket, cancellable, &error); if (!new_socket) { g_printerr ("Error accepting socket: %s\n", @@ -211,9 +211,11 @@ main (int argc, ensure_condition (recv_socket, "receive", cancellable, G_IO_IN); if (use_udp) size = g_socket_receive_from (recv_socket, &address, - buffer, sizeof buffer, &error); + buffer, sizeof buffer, + cancellable, &error); else - size = g_socket_receive (recv_socket, buffer, sizeof buffer, &error); + size = g_socket_receive (recv_socket, buffer, sizeof buffer, + cancellable, &error); if (size < 0) { @@ -243,9 +245,10 @@ main (int argc, ensure_condition (recv_socket, "send", cancellable, G_IO_OUT); if (use_udp) size = g_socket_send_to (recv_socket, address, - buffer, to_send, &error); + buffer, to_send, cancellable, &error); else - size = g_socket_send (recv_socket, buffer, to_send, &error); + size = g_socket_send (recv_socket, buffer, to_send, + cancellable, &error); if (size < 0) { |