[Telepathy-commits] [telepathy-idle/master] Handle buggy servers that don't quit properly

Jonathon Jongsma jonathon.jongsma at collabora.co.uk
Fri Feb 13 17:43:18 PST 2009


This fix kills 2 related bugs at once (and thus fixes both of the tests that I
just added on this branch).

1. It disables receiving further messages after we send our QUIT message, so
   that we don't process a stray "welcome" message and accidentally try to
   transition to CONNECTED state while we're in the middle of disconnecting.
2. Schedules a forceful server disconnection for 2s after we send our QUIT
   message in the case that the remote server does not close the socket.  This
   means that we send the dbus method return for Disconnect() at most 2s after
   receiving it, rather than depending on the remote server to disconnect us
   before we send the dbus method return.  I suppose I could have just
   disconnected immediately rather than scheduling it for 2s in the future, but
   I wanted to stay as close to current behavior as possible.
---
 src/idle-connection.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/src/idle-connection.c b/src/idle-connection.c
index 6c2d645..52faabf 100644
--- a/src/idle-connection.c
+++ b/src/idle-connection.c
@@ -152,6 +152,7 @@ struct _IdleConnectionPrivate {
 
 	/* if we are quitting asynchronously */
 	gboolean quitting;
+	guint force_disconnect_id;
 
 	/* AliasChanged aggregation */
 	GPtrArray *queued_aliases;
@@ -426,6 +427,15 @@ static gboolean _finish_shutdown_idle_func(gpointer data) {
 	return FALSE;
 }
 
+static gboolean
+_force_disconnect (gpointer data)
+{
+	IdleConnection *conn = IDLE_CONNECTION(data);
+	IdleConnectionPrivate *priv = IDLE_CONNECTION_GET_PRIVATE(conn);
+	idle_server_connection_iface_disconnect(priv->conn, NULL);
+	return FALSE;
+}
+
 static void _iface_disconnected(TpBaseConnection *self) {
 	IdleConnection *conn = IDLE_CONNECTION(self);
 	IdleConnectionPrivate *priv = IDLE_CONNECTION_GET_PRIVATE(conn);
@@ -433,6 +443,11 @@ static void _iface_disconnected(TpBaseConnection *self) {
 	send_quit_request(conn);
 
 	priv->quitting = TRUE;
+	/* don't handle any more messages, we're quitting.  See e.g. bug #19762 */
+	idle_parser_remove_handlers_by_data(conn->parser, conn);
+	/* schedule forceful disconnect for 2 seconds if the remote server doesn't
+	 * respond or disconnect before then */
+	priv->force_disconnect_id = g_timeout_add_seconds(2, _force_disconnect, conn);
 }
 
 static void _iface_shut_down(TpBaseConnection *self) {
@@ -519,6 +534,13 @@ static void sconn_status_changed_cb(IdleServerConnectionIface *sconn, IdleServer
 	IdleConnectionPrivate *priv = IDLE_CONNECTION_GET_PRIVATE(conn);
 	TpConnectionStatusReason tp_reason;
 
+	/* cancel scheduled forced disconnect since we are now disconnected */
+	if (state == SERVER_CONNECTION_STATE_NOT_CONNECTED &&
+		priv->force_disconnect_id) {
+		g_source_remove(priv->force_disconnect_id);
+		priv->force_disconnect_id = 0;
+	}
+
 	IDLE_DEBUG("called with state %u", state);
 
 	switch (reason) {
-- 
1.5.6.5




More information about the telepathy-commits mailing list