telepathy-idle: Fix _force_disconnect to actually forcibly disconnect.
Will Thompson
wjt at kemper.freedesktop.org
Fri Nov 2 04:56:49 PDT 2012
Module: telepathy-idle
Branch: master
Commit: 339c7273dcb604a639ea2b54461b24bd4f252dd6
URL: http://cgit.freedesktop.org/telepathy/telepathy-idle/commit/?id=339c7273dcb604a639ea2b54461b24bd4f252dd6
Author: Will Thompson <will.thompson at collabora.co.uk>
Date: Tue Oct 30 16:30:10 2012 +0000
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.
---
src/idle-connection.c | 18 ++++--------------
src/idle-server-connection.c | 17 +++++++++++++++++
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);
More information about the telepathy-commits
mailing list