summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2009-10-15 14:51:47 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2009-10-15 14:51:47 +0100
commit6ce9cb5fe15c46b159df114b123cf1f558a5824f (patch)
tree92be53a705a58febb419692c1e64c2e45db93b37
parentb6e5238667f3b25187399329d99a2ffe3d467cc1 (diff)
parentc24b6b4cf0d33a76fc1dd7b9af9efc89e5fd4de0 (diff)
Merge branch 'telepathy-glib-0.8'
Conflicts: NEWS
-rw-r--r--NEWS12
-rw-r--r--telepathy-glib/connection-manager.c115
2 files changed, 83 insertions, 44 deletions
diff --git a/NEWS b/NEWS
index ed6efef9e..31f0c631a 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,18 @@ Fixes:
* Work around GLib 2.20 being less const-correct than 2.22 (jonny)
+* fd.o #23853: if a connection manager is discovered not to be running while
+ TpConnectionManager has a ListProtocols call in-flight, then a new instance
+ of the CM starts up and replies to that call, don't crash with an assertion
+ failure (smcv)
+
+* If a connection manager returns error from GetParameters(), don't dereference
+ a NULL pointer and segfault (smcv)
+
+* When asked to activate or introspect a connection manager, don't do anything
+ until we have at least worked out whether it was initially running, in order
+ to provide the documented behaviour (smcv)
+
telepathy-glib 0.9.0 (2009-09-28)
=================================
diff --git a/telepathy-glib/connection-manager.c b/telepathy-glib/connection-manager.c
index 983da468f..193e3a049 100644
--- a/telepathy-glib/connection-manager.c
+++ b/telepathy-glib/connection-manager.c
@@ -181,12 +181,6 @@ struct _TpConnectionManagerPrivate {
/* source ID for introspecting later */
guint introspect_idle_id;
- /* FALSE if constructor hasn't run yet */
- unsigned constructed:1;
-
- /* TRUE if we're waiting for ListProtocols */
- unsigned listing_protocols:1;
-
/* TRUE if dispose() has run already */
unsigned disposed:1;
@@ -213,7 +207,13 @@ struct _TpConnectionManagerPrivate {
GList *waiting_for_ready;
/* the method call currently pending, or NULL if none. */
- TpProxyPendingCall *pending_get_params;
+ TpProxyPendingCall *introspection_call;
+
+ /* FALSE if initial name-owner (if any) hasn't been found yet */
+ gboolean name_known;
+ /* TRUE if someone asked us to activate but we're putting it off until
+ * name_known */
+ gboolean want_activation;
};
G_DEFINE_TYPE (TpConnectionManager,
@@ -403,12 +403,13 @@ tp_connection_manager_got_parameters (TpConnectionManager *self,
DEBUG ("Protocol name: %s", protocol);
- self->priv->pending_get_params = NULL;
+ g_assert (self->priv->introspection_call != NULL);
+ self->priv->introspection_call = NULL;
if (error != NULL)
{
DEBUG ("Error getting params for %s, skipping it", protocol);
- tp_connection_manager_continue_introspection (self);
+ goto out;
}
output = g_array_sized_new (TRUE, TRUE,
@@ -470,6 +471,7 @@ tp_connection_manager_got_parameters (TpConnectionManager *self,
(TpConnectionManagerParam *) g_array_free (output, FALSE);
g_ptr_array_add (self->priv->found_protocols, proto_struct);
+out:
tp_connection_manager_continue_introspection (self);
}
@@ -513,12 +515,10 @@ tp_connection_manager_end_introspection (TpConnectionManager *self,
{
guint i;
- self->priv->listing_protocols = FALSE;
-
- if (self->priv->pending_get_params != NULL)
+ if (self->priv->introspection_call != NULL)
{
- tp_proxy_pending_call_cancel (self->priv->pending_get_params);
- self->priv->pending_get_params = NULL;
+ tp_proxy_pending_call_cancel (self->priv->introspection_call);
+ self->priv->introspection_call = NULL;
}
if (self->priv->found_protocols != NULL)
@@ -577,7 +577,7 @@ tp_connection_manager_continue_introspection (TpConnectionManager *self)
next_protocol = g_ptr_array_remove_index_fast (self->priv->pending_protocols,
0);
- self->priv->pending_get_params =
+ self->priv->introspection_call =
tp_cli_connection_manager_call_get_parameters (self, -1, next_protocol,
tp_connection_manager_got_parameters, next_protocol, g_free,
NULL);
@@ -593,7 +593,8 @@ tp_connection_manager_got_protocols (TpConnectionManager *self,
guint i = 0;
const gchar **iter;
- self->priv->listing_protocols = FALSE;
+ g_assert (self->priv->introspection_call != NULL);
+ self->priv->introspection_call = NULL;
if (error != NULL)
{
@@ -633,7 +634,8 @@ tp_connection_manager_got_protocols (TpConnectionManager *self,
static gboolean
introspection_in_progress (TpConnectionManager *self)
{
- return self->priv->listing_protocols || self->priv->found_protocols != NULL;
+ return (self->priv->introspection_call != NULL ||
+ self->priv->found_protocols != NULL);
}
static gboolean
@@ -646,12 +648,10 @@ tp_connection_manager_idle_introspect (gpointer data)
(self->always_introspect ||
self->info_source == TP_CM_INFO_SOURCE_NONE))
{
- self->priv->listing_protocols = TRUE;
-
DEBUG ("calling ListProtocols on CM");
- tp_cli_connection_manager_call_list_protocols (self, -1,
- tp_connection_manager_got_protocols, NULL, NULL,
- NULL);
+ self->priv->introspection_call =
+ tp_cli_connection_manager_call_list_protocols (self, -1,
+ tp_connection_manager_got_protocols, NULL, NULL, NULL);
}
self->priv->introspect_idle_id = 0;
@@ -659,6 +659,8 @@ tp_connection_manager_idle_introspect (gpointer data)
return FALSE;
}
+static gboolean tp_connection_manager_idle_read_manager_file (gpointer data);
+
static void
tp_connection_manager_name_owner_changed_cb (TpDBusDaemon *bus,
const gchar *name,
@@ -681,7 +683,12 @@ tp_connection_manager_name_owner_changed_cb (TpDBusDaemon *bus,
if (introspection_in_progress (self))
tp_connection_manager_end_introspection (self, &e);
- g_signal_emit (self, signals[SIGNAL_EXITED], 0);
+ /* If our name wasn't known already, a change to "" is just the initial
+ * state, so we didn't *exit* as such. */
+ if (self->priv->name_known)
+ {
+ g_signal_emit (self, signals[SIGNAL_EXITED], 0);
+ }
}
else
{
@@ -698,6 +705,27 @@ tp_connection_manager_name_owner_changed_cb (TpDBusDaemon *bus,
tp_connection_manager_idle_introspect, self);
}
+ /* if we haven't started introspecting yet, now would be a good time */
+ if (!self->priv->name_known)
+ {
+ g_assert (self->priv->manager_file_read_idle_id == 0);
+
+ /* now we know whether we're running or not, we can try reading the
+ * .manager file... */
+ self->priv->manager_file_read_idle_id = g_idle_add (
+ tp_connection_manager_idle_read_manager_file, self);
+
+ if (self->priv->want_activation && self->priv->introspect_idle_id == 0)
+ {
+ /* ... but if activation was requested, we should also do that */
+ self->priv->introspect_idle_id = g_idle_add (
+ tp_connection_manager_idle_introspect, self);
+ }
+
+ /* Unfreeze automatic reading of .manager file if manager-file changes */
+ self->priv->name_known = TRUE;
+ }
+
g_object_unref (self);
}
@@ -1235,14 +1263,6 @@ tp_connection_manager_constructor (GType type,
tp_connection_manager_find_manager_file (self->name);
}
- g_assert (self->priv->manager_file_read_idle_id == 0);
-
- self->priv->manager_file_read_idle_id = g_idle_add (
- tp_connection_manager_idle_read_manager_file, self);
-
- /* Unfreeze automatic reading of .manager file if manager-file changes */
- self->priv->constructed = TRUE;
-
return (GObject *) self;
}
@@ -1352,12 +1372,12 @@ tp_connection_manager_set_property (GObject *object,
case PROP_MANAGER_FILE:
g_free (self->priv->manager_file);
- /* If the constructor has already run, change the definition of where
+ /* If initial code has already run, change the definition of where
* we expect to find the .manager file and trigger re-introspection.
- * Otherwise, just take the value - _constructor queues the first-time
- * manager file lookup anyway.
+ * Otherwise, just take the value - when name_known becomes TRUE we
+ * queue the first-time manager file lookup anyway.
*/
- if (self->priv->constructed)
+ if (self->priv->name_known)
{
const gchar *tmp = g_value_get_string (value);
@@ -1637,17 +1657,24 @@ tp_connection_manager_new (TpDBusDaemon *dbus,
gboolean
tp_connection_manager_activate (TpConnectionManager *self)
{
- if (self->running || introspection_in_progress (self))
+ if (self->priv->name_known)
{
- DEBUG ("already %s", self->running ? "running" : "introspecting");
- return FALSE;
- }
-
- DEBUG ("calling ListProtocols");
+ if (self->running)
+ {
+ DEBUG ("already running");
+ return FALSE;
+ }
- self->priv->listing_protocols = TRUE;
- tp_cli_connection_manager_call_list_protocols (self, -1,
- tp_connection_manager_got_protocols, NULL, NULL, NULL);
+ if (self->priv->introspect_idle_id == 0)
+ self->priv->introspect_idle_id = g_idle_add (
+ tp_connection_manager_idle_introspect, self);
+ }
+ else
+ {
+ /* we'll activate later, when we know properly whether we're running */
+ DEBUG ("queueing activation for when we know what's going on");
+ self->priv->want_activation = TRUE;
+ }
return TRUE;
}