[Telepathy-commits] [telepathy-haze/master] Keep track of whether purple_account_disconnect needs to be called.

Will Thompson will.thompson at collabora.co.uk
Thu Aug 14 03:37:38 PDT 2008


This fixes #14933.  When libpurple reports a connection error, it
schedules an idle callback for purple_account_disconnect.  Haze's
implementation of TpBaseConnection->shut_down checked
PurpleAccount->disconnecting before calling purple_account_disconnect,
but that flag is only set once purple_account_disconnect is actually
called.  So purple_account_disconnect would be called twice, and if you
got unlucky the account have been freed before the second call, causing
catastrophe.
---
 src/connection.c |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/src/connection.c b/src/connection.c
index 14a1051..c0863e1 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -63,6 +63,11 @@ typedef struct _HazeConnectionPrivate
 
     HazeProtocolInfo *protocol_info;
 
+    /* Set if purple_account_disconnect has been called or is scheduled to be
+     * called, so should not be called again.
+     */
+    gboolean disconnecting;
+
     gboolean dispose_has_run;
 } HazeConnectionPrivate;
 
@@ -115,10 +120,17 @@ haze_report_disconnect_reason (PurpleConnection *gc,
                                const char *text)
 {
     PurpleAccount *account = purple_connection_get_account (gc);
+    HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account);
+    HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE (conn);
     TpBaseConnection *base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account);
 
     TpConnectionStatusReason tp_reason;
 
+    /* When a connection error is reported by libpurple, an idle callback to
+     * purple_account_disconnect is added.
+     */
+    priv->disconnecting = TRUE;
+
     switch (reason)
     {
         case PURPLE_CONNECTION_ERROR_NETWORK_ERROR:
@@ -196,8 +208,12 @@ void
 disconnected_cb (PurpleConnection *pc)
 {
     PurpleAccount *account = purple_connection_get_account (pc);
+    HazeConnection *conn = ACCOUNT_GET_HAZE_CONNECTION (account);
+    HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE (conn);
     TpBaseConnection *base_conn = ACCOUNT_GET_TP_BASE_CONNECTION (account);
 
+    priv->disconnecting = TRUE;
+
     if(base_conn->status != TP_CONNECTION_STATUS_DISCONNECTED)
     {
         tp_base_connection_change_status (base_conn,
@@ -326,8 +342,12 @@ static void
 _haze_connection_shut_down (TpBaseConnection *base)
 {
     HazeConnection *self = HAZE_CONNECTION(base);
-    if(!self->account->disconnecting)
+    HazeConnectionPrivate *priv = HAZE_CONNECTION_GET_PRIVATE (self);
+    if(!priv->disconnecting)
+    {
+        priv->disconnecting = TRUE;
         purple_account_disconnect(self->account);
+    }
 }
 
 /* Must be in the same order as HazeListHandle in connection.h */
@@ -452,6 +472,8 @@ haze_connection_constructor (GType type,
 
     priv->dispose_has_run = FALSE;
 
+    priv->disconnecting = FALSE;
+
     _create_account (self);
 
     return (GObject *)self;
-- 
1.5.6.3




More information about the Telepathy-commits mailing list