[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