diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2012-10-30 16:30:10 +0000 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2012-10-30 16:30:10 +0000 |
commit | 339c7273dcb604a639ea2b54461b24bd4f252dd6 (patch) | |
tree | 42235f762b78762aa10741f760a429f7a0529f00 /src | |
parent | 67b18831e0ea40dd3f4438426cfb0f703a3fc971 (diff) | |
download | telepathy-idle-339c7273dcb604a639ea2b54461b24bd4f252dd6.tar.gz |
Fix _force_disconnect to actually forcibly disconnect.
Previously, if the network connection had gone away _force_disconnect()
would not actually make the connection die any faster, because
g_io_stream_close_async() waits for a reply by default.
But by pulling the same trick with a cancelled cancellable as is used
for ping timeouts, we can fix this.
I tested this by:
* Connecting to a server (with keepalive-interval=0 to ensure that
doesn't interfere).
* Pulling out my network cable (breaking the connection) but leaving my
wireless connection up.
* calling Disconnect() on the connection.
Before, the connection would never finish disconnecting; after, the
_force_disconnect() timeout actually does something useful and the
connection dies properly.
Diffstat (limited to 'src')
-rw-r--r-- | src/idle-connection.c | 18 | ||||
-rw-r--r-- | src/idle-server-connection.c | 17 | ||||
-rw-r--r-- | src/idle-server-connection.h | 1 |
3 files changed, 22 insertions, 14 deletions
diff --git a/src/idle-connection.c b/src/idle-connection.c index cb008c5..a7c4f73 100644 --- a/src/idle-connection.c +++ b/src/idle-connection.c @@ -567,7 +567,9 @@ _force_disconnect (gpointer data) { IdleConnection *conn = IDLE_CONNECTION(data); IdleConnectionPrivate *priv = conn->priv; - idle_server_connection_disconnect_async(priv->conn, NULL, NULL, NULL); + + IDLE_DEBUG("gave up waiting, forcibly disconnecting"); + idle_server_connection_force_disconnect(priv->conn); return FALSE; } @@ -830,23 +832,11 @@ static gboolean keepalive_timeout_cb(gpointer user_data) { gint64 seconds_since_ping = (now - priv->ping_time) / G_USEC_PER_SEC; if (seconds_since_ping > priv->keepalive_interval * MISSED_KEEPALIVES_BEFORE_DISCONNECTING) { - GCancellable *kill_me_now = g_cancellable_new(); - IDLE_DEBUG("haven't heard from the server in %" G_GINT64_FORMAT " seconds " "(more than %u keepalive intervals)", seconds_since_ping, MISSED_KEEPALIVES_BEFORE_DISCONNECTING); - /* Passing a cancelled cancellable to g_io_stream_close_async() stops us - * waiting for a TCP-level reply from the server which we already know - * has gone away. Quoth the docs for g_io_stream_close(): - * - * Cancelling a close will still leave the stream closed, but some - * streams can use a faster close that doesn't block to e.g. check - * errors. - */ - g_cancellable_cancel(kill_me_now); - idle_server_connection_disconnect_full_async(priv->conn, SERVER_CONNECTION_STATE_REASON_ERROR, kill_me_now, NULL, NULL); - g_object_unref(kill_me_now); + idle_server_connection_force_disconnect(priv->conn); return FALSE; } diff --git a/src/idle-server-connection.c b/src/idle-server-connection.c index 64cb766..700b5f8 100644 --- a/src/idle-server-connection.c +++ b/src/idle-server-connection.c @@ -362,6 +362,23 @@ void idle_server_connection_disconnect_async(IdleServerConnection *conn, GCancel user_data); } +void idle_server_connection_force_disconnect(IdleServerConnection *conn) { + /* Passing a cancelled cancellable to g_io_stream_close_async() stops us + * waiting for a TCP-level reply from the server which we already know + * has gone away. Quoth the docs for g_io_stream_close(): + * + * Cancelling a close will still leave the stream closed, but some + * streams can use a faster close that doesn't block to e.g. check + * errors. + */ + GCancellable *kill_me_now = g_cancellable_new(); + + g_cancellable_cancel(kill_me_now); + idle_server_connection_disconnect_full_async(conn, + SERVER_CONNECTION_STATE_REASON_ERROR, kill_me_now, NULL, NULL); + g_object_unref(kill_me_now); +} + void idle_server_connection_disconnect_full_async(IdleServerConnection *conn, guint reason, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { IdleServerConnectionPrivate *priv = IDLE_SERVER_CONNECTION_GET_PRIVATE(conn); GSimpleAsyncResult *result; diff --git a/src/idle-server-connection.h b/src/idle-server-connection.h index 207fedc..8ce36ca 100644 --- a/src/idle-server-connection.h +++ b/src/idle-server-connection.h @@ -73,6 +73,7 @@ void idle_server_connection_connect_async(IdleServerConnection *conn, GCancellab gboolean idle_server_connection_connect_finish(IdleServerConnection *conn, GAsyncResult *result, GError **error); void idle_server_connection_disconnect_async(IdleServerConnection *conn, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); void idle_server_connection_disconnect_full_async(IdleServerConnection *conn, guint reason, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); +void idle_server_connection_force_disconnect(IdleServerConnection *conn); gboolean idle_server_connection_disconnect_finish(IdleServerConnection *conn, GAsyncResult *result, GError **error); void idle_server_connection_send_async(IdleServerConnection *conn, const gchar *cmd, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); gboolean idle_server_connection_send_finish(IdleServerConnection *conn, GAsyncResult *result, GError **error); |