summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLionel Landwerlin <llandwerlin@gmail.com>2013-08-29 23:48:10 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2013-09-05 13:47:03 +0100
commit42fd234c2336718a93993829c4d55c819b172012 (patch)
treef2bc1115bab9ee1fb1c30d14596bdcaa5e9d10f8
parent231b12a7d127f07fc83b1c4486ddba9c65a16f66 (diff)
ServerConnection: kill async read when disconnecting
GSocket creates GSources to provide GInputStream and GOutputStream objects. Interestingly, it doesn't set the GIOCondition on the GSource to handle G_IO_NVAL (ie. your file descriptor is not valid anymore). It means that if your trying to read asynchronously from the socket while someone else closes the socket, you end with an GInputStream that can never complete its asynchronous read operation because the file descriptor isn't valid anymore but that isn't a condition to dispatch the GSource and end the asynchronous read with an error. Alternatively, this wakes up the gmainloop all the time => 100% cpu consumption. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=64923 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
-rw-r--r--src/idle-server-connection.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/idle-server-connection.c b/src/idle-server-connection.c
index b593fa3..a921c33 100644
--- a/src/idle-server-connection.c
+++ b/src/idle-server-connection.c
@@ -71,6 +71,7 @@ struct _IdleServerConnectionPrivate {
GSocketClient *socket_client;
GIOStream *io_stream;
+ GCancellable *read_cancellable;
GCancellable *cancellable;
IdleServerConnectionState state;
@@ -245,8 +246,12 @@ static void change_state(IdleServerConnection *conn, IdleServerConnectionState s
static void _input_stream_read(IdleServerConnection *conn, GInputStream *input_stream, GAsyncReadyCallback callback) {
IdleServerConnectionPrivate *priv = IDLE_SERVER_CONNECTION_GET_PRIVATE(conn);
+ if (priv->read_cancellable == NULL)
+ priv->read_cancellable = g_cancellable_new ();
+
+
memset(priv->input_buffer, '\0', sizeof(priv->input_buffer));
- g_input_stream_read_async (input_stream, &priv->input_buffer, sizeof(priv->input_buffer) - 1, G_PRIORITY_DEFAULT, NULL, callback, conn);
+ g_input_stream_read_async (input_stream, &priv->input_buffer, sizeof(priv->input_buffer) - 1, G_PRIORITY_DEFAULT, priv->read_cancellable, callback, conn);
}
static void _input_stream_read_ready(GObject *source_object, GAsyncResult *res, gpointer user_data) {
@@ -514,6 +519,9 @@ void idle_server_connection_disconnect_full_async(IdleServerConnection *conn, gu
priv->reason = reason;
+ g_cancellable_cancel (priv->read_cancellable);
+ g_clear_object (&priv->read_cancellable);
+
result = g_simple_async_result_new(G_OBJECT(conn), callback, user_data, idle_server_connection_disconnect_full_async);
g_io_stream_close_async(priv->io_stream, G_PRIORITY_DEFAULT, cancellable, _close_ready, result);
g_object_unref(priv->io_stream);