telepathy-idle: Connection: cancel connect_async when Disconnect() is called

Simon McVittie smcv at kemper.freedesktop.org
Wed May 1 09:01:43 PDT 2013


Module: telepathy-idle
Branch: master
Commit: b80deba63f3fafb46cfaa65a661f9929b5c1063b
URL:    http://cgit.freedesktop.org/telepathy/telepathy-idle/commit/?id=b80deba63f3fafb46cfaa65a661f9929b5c1063b

Author: Will Thompson <will.thompson at collabora.co.uk>
Date:   Tue Apr 30 16:59:22 2013 +0100

Connection: cancel connect_async when Disconnect() is called

---

 src/idle-connection.c                              |   12 ++++++-
 src/idle-server-connection.c                       |    3 +-
 tests/twisted/Makefile.am                          |    1 +
 .../connect/disconnect-before-socket-connected.py  |   31 ++++++++++++++++++++
 4 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/src/idle-connection.c b/src/idle-connection.c
index b881295..182108e 100644
--- a/src/idle-connection.c
+++ b/src/idle-connection.c
@@ -152,6 +152,9 @@ struct _IdleConnectionPrivate {
 	 */
 	gboolean sconn_connected;
 
+	/* Used for idle_server_connection_connect_async(). */
+	GCancellable *connect_cancellable;
+
 	/* When we sent a PING to the server which it hasn't PONGed for yet, or 0 if
 	 * there isn't a PING outstanding.
 	 */
@@ -408,6 +411,8 @@ static void idle_connection_dispose (GObject *object) {
 		priv->conn = NULL;
 	}
 
+	g_clear_object (&priv->connect_cancellable);
+
 	if (priv->queued_aliases_owners)
 		tp_handle_set_destroy(priv->queued_aliases_owners);
 
@@ -620,7 +625,8 @@ static void _iface_shut_down(TpBaseConnection *base) {
 	if (priv->conn == NULL) {
 		g_idle_add(_finish_shutdown_idle_func, self);
 	} else if (!priv->sconn_connected) {
-		IDLE_DEBUG("TODO: cancel connecting");
+		IDLE_DEBUG("cancelling connection");
+		g_cancellable_cancel (priv->connect_cancellable);
 	} else {
 		idle_server_connection_disconnect_async(priv->conn, NULL, NULL, NULL);
 	}
@@ -762,7 +768,9 @@ static void _start_connecting_continue(IdleConnection *conn) {
 	g_signal_connect(sconn, "disconnected", (GCallback)(sconn_disconnected_cb), conn);
 
 	priv->conn = sconn;
-	idle_server_connection_connect_async(sconn, NULL, _connection_connect_ready, conn);
+	g_warn_if_fail (priv->connect_cancellable == NULL);
+	priv->connect_cancellable = g_cancellable_new ();
+	idle_server_connection_connect_async(sconn, priv->connect_cancellable, _connection_connect_ready, conn);
 }
 
 static gboolean keepalive_timeout_cb(gpointer user_data);
diff --git a/src/idle-server-connection.c b/src/idle-server-connection.c
index f1c7ce1..bc7a972 100644
--- a/src/idle-server-connection.c
+++ b/src/idle-server-connection.c
@@ -431,8 +431,7 @@ void idle_server_connection_connect_async(IdleServerConnection *conn, GCancellab
 
 	result = g_simple_async_result_new(G_OBJECT(conn), callback, user_data, idle_server_connection_connect_async);
 
-	task = g_task_new (conn, cancellable,
-		_connect_to_host_ready, result);
+	task = g_task_new (conn, cancellable, _connect_to_host_ready, result);
 	g_task_run_in_thread (task, _connect_in_thread);
 
 	change_state(conn, SERVER_CONNECTION_STATE_CONNECTING, SERVER_CONNECTION_STATE_REASON_REQUESTED);
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 6063454..764f074 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -6,6 +6,7 @@ TWISTED_TESTS = \
 		connect/connect-reject-ssl.py \
 		connect/connect-fail.py \
 		connect/connect-fail-ssl.py \
+		connect/disconnect-before-socket-connected.py \
 		connect/disconnect-during-cert-verification.py \
 		connect/ping.py \
 		connect/server-quit-ignore.py \
diff --git a/tests/twisted/connect/disconnect-before-socket-connected.py b/tests/twisted/connect/disconnect-before-socket-connected.py
new file mode 100644
index 0000000..8fc89e0
--- /dev/null
+++ b/tests/twisted/connect/disconnect-before-socket-connected.py
@@ -0,0 +1,31 @@
+"""
+Test disconnecting before the TCP session is established.
+"""
+
+from idletest import exec_test
+from servicetest import call_async
+
+def test(q, bus, conn, stream):
+    conn.Connect()
+    q.expect('dbus-signal', signal='StatusChanged', args=[1, 1])
+
+    # We want the call to Disconnect to reach Idle before the call to
+    # g_socket_client_connect_to_host(), which connects to this Python process,
+    # completes. I tried making the Twisted infrastructure stop calling
+    # .accept() but that doesn't seem to have any effect.
+    #
+    # But! All is not lost! Making a blocking call to Disconnect() does the
+    # job, because we block in libdbus and Twisted doesn't get a chance to poll
+    # the listening socket until Disconnect() returns.
+    conn.Disconnect()
+
+    # The bug was that Idle would not try to cancel the in-progress connection
+    # attempt. It worked when the connection was blocked on TLS verification
+    # (see disconnect-during-cert-verification.py) because closing that channel
+    # (as a side-effect of disconnecting) caused the TCP connection attempt to
+    # fail, but didn't work in this case.
+    q.expect('dbus-signal', signal='StatusChanged', args=[2, 1])
+
+if __name__ == '__main__':
+    exec_test(test)
+



More information about the telepathy-commits mailing list