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