From f47e935e450c132a48d6945cd553ec24b794c708 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Wed, 10 Oct 2012 08:41:28 -0400 Subject: [PATCH] Bug 685713 - ESourceRegistry's manager thread aborts on error If the ESourceRegistry's manager thread fails to create a new GDBusObjectManagerClient during initialization, propagate the GError back to the caller of e_source_registry_new() instead of aborting the whole process with a g_error() call. --- libedataserver/e-source-registry.c | 72 ++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 30 deletions(-) diff --git a/libedataserver/e-source-registry.c b/libedataserver/e-source-registry.c index b5632cd..3933712 100644 --- a/libedataserver/e-source-registry.c +++ b/libedataserver/e-source-registry.c @@ -146,6 +146,7 @@ struct _ThreadClosure { GMainLoop *main_loop; GCond *main_loop_cond; GMutex *main_loop_mutex; + GError *error; }; enum { @@ -241,6 +242,10 @@ thread_closure_free (ThreadClosure *closure) g_cond_free (closure->main_loop_cond); g_mutex_free (closure->main_loop_mutex); + /* The GError should be NULL at this point, + * regardless of whether an error occurred. */ + g_warn_if_fail (closure->error == NULL); + g_slice_free (ThreadClosure, closure); } @@ -711,9 +716,8 @@ source_registry_object_manager_thread (gpointer data) ThreadClosure *closure = data; GSource *idle_source; GList *list, *link; - gulong object_added_id; - gulong object_removed_id; - GError *error = NULL; + gulong object_added_id = 0; + gulong object_removed_id = 0; /* GDBusObjectManagerClient grabs the thread-default GMainContext * at creation time and only emits signals from that GMainContext. @@ -731,15 +735,19 @@ source_registry_object_manager_thread (gpointer data) G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, SOURCES_DBUS_SERVICE_NAME, DBUS_OBJECT_PATH, - NULL, &error); + NULL, &closure->error); - /* If this fails there's really no point in continuing - * since we rely on the object manager to populate the - * registry. Abort the process with a fatal error. */ - if (error != NULL) { - g_error ("%s", error->message); - g_assert_not_reached (); - } + /* Sanity check. */ + g_warn_if_fail ( + ((object_manager != NULL) && (closure->error == NULL)) || + ((object_manager == NULL) && (closure->error != NULL))); + + /* If we failed to create the GDBusObjectManagerClient, skip + * straight to the main loop. The GError will be propagated + * back to the caller, the main loop will terminate, and the + * partially-initialized ESourceRegistry will be destroyed. */ + if (object_manager == NULL) + goto notify; /* Give the registry a handle to the object manager. */ closure->registry->priv->dbus_object_manager = @@ -767,17 +775,6 @@ source_registry_object_manager_thread (gpointer data) g_list_free_full (list, (GDestroyNotify) g_object_unref); - /* Schedule a one-time idle callback to broadcast through a - * condition variable that our main loop is up and running. */ - - idle_source = g_idle_source_new (); - g_source_set_callback ( - idle_source, - source_registry_object_manager_running, - closure, (GDestroyNotify) NULL); - g_source_attach (idle_source, closure->main_context); - g_source_unref (idle_source); - /* Listen for D-Bus object additions and removals. */ object_added_id = g_signal_connect ( @@ -790,16 +787,29 @@ source_registry_object_manager_thread (gpointer data) G_CALLBACK (source_registry_object_removed_cb), closure->registry); +notify: + /* Schedule a one-time idle callback to broadcast through a + * condition variable that our main loop is up and running. */ + + idle_source = g_idle_source_new (); + g_source_set_callback ( + idle_source, + source_registry_object_manager_running, + closure, (GDestroyNotify) NULL); + g_source_attach (idle_source, closure->main_context); + g_source_unref (idle_source); + /* Now we mostly idle here for the rest of the session. */ g_main_loop_run (closure->main_loop); /* Clean up and exit. */ - g_signal_handler_disconnect (object_manager, object_added_id); - g_signal_handler_disconnect (object_manager, object_removed_id); - - g_object_unref (object_manager); + if (object_manager != NULL) { + g_signal_handler_disconnect (object_manager, object_added_id); + g_signal_handler_disconnect (object_manager, object_removed_id); + g_object_unref (object_manager); + } g_main_context_pop_thread_default (closure->main_context); @@ -1005,10 +1015,12 @@ source_registry_initable_init (GInitable *initable, closure->main_loop_mutex); g_mutex_unlock (closure->main_loop_mutex); - /* We should now have a GDBusObjectManagerClient available. */ - g_return_val_if_fail ( - G_IS_DBUS_OBJECT_MANAGER_CLIENT ( - registry->priv->dbus_object_manager), FALSE); + /* Check for error in the manager thread. */ + if (closure->error != NULL) { + g_propagate_error (error, closure->error); + closure->error = NULL; + return FALSE; + } /* The registry should now be populated with sources. */ g_warn_if_fail (g_hash_table_size (registry->priv->sources) > 0); -- 2.7.4