aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2009-01-31 01:16:02 +0800
committerXavier Claessens <xclaesse@src.gnome.org>2009-01-31 01:16:02 +0800
commit28258efc5b743fb8ef6eec1ac5466dc8038e3f6f (patch)
tree41f2fc4a49561d99bc844eb0854cfa12ea43484b
parent287688f54b5580b08db118478bd16bca1a1c6347 (diff)
downloadgsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.tar
gsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.tar.gz
gsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.tar.bz2
gsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.tar.lz
gsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.tar.xz
gsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.tar.zst
gsoc2013-empathy-28258efc5b743fb8ef6eec1ac5466dc8038e3f6f.zip
Allow the dispatcher to be freed once a request is finished.
Previously, if there was no ref to the dispatcher, it would be freed before the request could be satisfied. By keeping a ref in the DispatcherRequestData, it is freed at the right time. This also disconnects the signal handler from all channels and connections when freeing the dispatcher as the "invalidated" signal callback can be called after the dispatcher has been freed. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk> svn path=/trunk/; revision=2306
-rw-r--r--libempathy/empathy-dispatcher.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c
index e8f7b8c7e..a8e0b1844 100644
--- a/libempathy/empathy-dispatcher.c
+++ b/libempathy/empathy-dispatcher.c
@@ -57,6 +57,9 @@ typedef struct
GHashTable *accounts;
gpointer token;
GSList *tubes;
+
+ /* channels which the dispatcher is listening "invalidated" */
+ GList *channels;
} EmpathyDispatcherPriv;
G_DEFINE_TYPE (EmpathyDispatcher, empathy_dispatcher, G_TYPE_OBJECT);
@@ -142,7 +145,7 @@ new_dispatcher_request_data (EmpathyDispatcher *dispatcher,
{
DispatcherRequestData *result = g_slice_new0 (DispatcherRequestData);
- result->dispatcher = dispatcher;
+ result->dispatcher = g_object_ref (dispatcher);
result->connection = connection;
result->channel_type = g_strdup (channel_type);
@@ -164,6 +167,9 @@ free_dispatcher_request_data (DispatcherRequestData *r)
{
g_free (r->channel_type);
+ if (r->dispatcher != NULL)
+ g_object_unref (r->dispatcher);
+
if (r->contact != NULL)
g_object_unref (r->contact);
@@ -306,6 +312,8 @@ dispatcher_channel_invalidated_cb (TpProxy *proxy,
g_hash_table_remove (cd->dispatched_channels, object_path);
g_hash_table_remove (cd->dispatching_channels, object_path);
+ priv->channels = g_list_remove (priv->channels, proxy);
+
operation = g_hash_table_lookup (cd->outstanding_channels, object_path);
if (operation != NULL)
{
@@ -387,6 +395,7 @@ dispatch_operation_ready_cb (EmpathyDispatchOperation *operation,
g_object_unref (G_OBJECT (connection));
g_object_ref (operation);
+ g_object_ref (dispatcher);
dispatch_operation_flush_requests (dispatcher, operation, NULL, cd);
status = empathy_dispatch_operation_get_status (operation);
@@ -409,6 +418,7 @@ dispatch_operation_ready_cb (EmpathyDispatchOperation *operation,
g_signal_emit (dispatcher, signals[DISPATCH], 0, operation);
}
+ g_object_unref (dispatcher);
}
static void
@@ -549,6 +559,8 @@ dispatcher_connection_new_channel (EmpathyDispatcher *dispatcher,
G_CALLBACK (dispatcher_channel_invalidated_cb),
dispatcher);
+ priv->channels = g_list_append (priv->channels, channel);
+
if (handle_type == TP_CONN_HANDLE_TYPE_CONTACT)
{
EmpathyContactFactory *factory = empathy_contact_factory_dup_singleton ();
@@ -755,7 +767,6 @@ dispatcher_connection_ready_cb (TpConnection *connection,
g_signal_connect (connection, "invalidated",
G_CALLBACK (dispatcher_connection_invalidated_cb), dispatcher);
-
if (tp_proxy_has_interface_by_id (TP_PROXY (connection),
TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS))
{
@@ -866,10 +877,28 @@ static void
dispatcher_finalize (GObject *object)
{
EmpathyDispatcherPriv *priv = GET_PRIV (object);
+ GList *l;
+ GHashTableIter iter;
+ gpointer connection;
g_signal_handlers_disconnect_by_func (priv->account_manager,
dispatcher_account_connection_cb, object);
+ for (l = priv->channels; l; l = l->next)
+ {
+ g_signal_handlers_disconnect_by_func (l->data,
+ dispatcher_channel_invalidated_cb, object);
+ }
+
+ g_list_free (priv->channels);
+
+ g_hash_table_iter_init (&iter, priv->connections);
+ while (g_hash_table_iter_next (&iter, &connection, NULL))
+ {
+ g_signal_handlers_disconnect_by_func (connection,
+ dispatcher_connection_invalidated_cb, object);
+ }
+
g_object_unref (priv->account_manager);
g_object_unref (priv->mc);
@@ -941,6 +970,8 @@ empathy_dispatcher_init (EmpathyDispatcher *dispatcher)
priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
g_object_unref, (GDestroyNotify) free_connection_data);
+ priv->channels = NULL;
+
accounts = mc_accounts_list_by_enabled (TRUE);
for (l = accounts; l; l = l->next)
@@ -1034,6 +1065,8 @@ dispatcher_connection_new_requested_channel (EmpathyDispatcher *dispatcher,
G_CALLBACK (dispatcher_channel_invalidated_cb),
request_data->dispatcher);
+ priv->channels = g_list_append (priv->channels, channel);
+
operation = empathy_dispatch_operation_new (request_data->connection,
channel, request_data->contact, FALSE);
g_object_unref (channel);