[evolution-data-server/gnome-3-8] EBookClientView: Make D-Bus signal handlers thread-safe.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/gnome-3-8] EBookClientView: Make D-Bus signal handlers thread-safe.
- Date: Sat, 4 May 2013 16:58:55 +0000 (UTC)
commit b5a4cd68cde6d5589325b7525dfc1f2baaecc570
Author: Matthew Barnes <mbarnes redhat com>
Date: Sat May 4 10:32:36 2013 -0400
EBookClientView: Make D-Bus signal handlers thread-safe.
Seeing crashes now where handler functions for D-Bus signals like
"objects-added" are receiving finalized EBookClientView instances.
Possibly a side-effect of recent changes to GMainContext usage.
Use the trick of passing an allocated GWeakRef along with a suitable
GClosureNotify to g_signal_connect_data(). The handler function will
just return quietly if it can't obtain a strong client view reference.
(cherry picked from commit 2df7a66eb535863dc41db446afc67ca4e0268c12)
Conflicts:
addressbook/libebook/e-book-client-view.c
addressbook/libebook/e-book-client-view.c | 313 ++++++++++++++++++-----------
1 files changed, 198 insertions(+), 115 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
index 25f47c9..275fa00 100644
--- a/addressbook/libebook/e-book-client-view.c
+++ b/addressbook/libebook/e-book-client-view.c
@@ -126,6 +126,24 @@ signal_closure_free (SignalClosure *signal_closure)
g_slice_free (SignalClosure, signal_closure);
}
+static GWeakRef *
+weak_ref_new (gpointer object)
+{
+ GWeakRef *weak_ref;
+
+ weak_ref = g_slice_new0 (GWeakRef);
+ g_weak_ref_set (weak_ref, object);
+
+ return weak_ref;
+}
+
+static void
+weak_ref_free (GWeakRef *weak_ref)
+{
+ g_weak_ref_set (weak_ref, NULL);
+ g_slice_free (GWeakRef, weak_ref);
+}
+
static GMainContext *
book_client_view_ref_main_context (EBookClientView *client_view)
{
@@ -423,166 +441,221 @@ direct_contacts_fetch (EBookClientView *view,
static void
book_client_view_objects_added_cb (EGdbusBookView *object,
const gchar * const *vcards,
- EBookClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- GSList *list = NULL;
- gint ii;
+ EBookClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- /* array contains UIDs only */
- if (client_view->priv->direct_book != NULL) {
- direct_contacts_fetch (client_view, vcards, OBJECTS_ADDED);
- return;
- }
+ if (client_view != NULL) {
+ GSList *list = NULL;
+ gint ii;
- /* array contains both UID and vcard */
- for (ii = 0; vcards[ii] != NULL && vcards[ii + 1] != NULL; ii += 2) {
- EContact *contact;
- const gchar *vcard = vcards[ii];
- const gchar *uid = vcards[ii + 1];
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- contact = e_contact_new_from_vcard_with_uid (vcard, uid);
- list = g_slist_prepend (list, contact);
- }
+ /* array contains UIDs only */
+ if (client_view->priv->direct_book != NULL) {
+ direct_contacts_fetch (
+ client_view, vcards, OBJECTS_ADDED);
+ g_object_unref (client_view);
+ return;
+ }
- list = g_slist_reverse (list);
+ /* array contains both UID and vcard */
+ for (ii = 0; vcards[ii] != NULL && vcards[ii + 1] != NULL; ii += 2) {
+ EContact *contact;
+ const gchar *vcard = vcards[ii];
+ const gchar *uid = vcards[ii + 1];
- /* Takes ownership of the linked list. */
- book_client_view_emit_objects_added (client_view, list);
+ contact = e_contact_new_from_vcard_with_uid (vcard, uid);
+ list = g_slist_prepend (list, contact);
+ }
+
+ list = g_slist_reverse (list);
+
+ /* Takes ownership of the linked list. */
+ book_client_view_emit_objects_added (client_view, list);
+
+ g_object_unref (client_view);
+ }
}
static void
book_client_view_objects_modified_cb (EGdbusBookView *object,
const gchar * const *vcards,
- EBookClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- GSList *list = NULL;
- gint ii;
+ EBookClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- /* array contains UIDs only */
- if (client_view->priv->direct_book != NULL) {
- direct_contacts_fetch (client_view, vcards, OBJECTS_MODIFIED);
- return;
- }
+ if (client_view != NULL) {
+ GSList *list = NULL;
+ gint ii;
- /* array contains both UID and vcard */
- for (ii = 0; vcards[ii] != NULL && vcards[ii + 1] != NULL; ii += 2) {
- EContact *contact;
- const gchar *vcard = vcards[ii];
- const gchar *uid = vcards[ii + 1];
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- contact = e_contact_new_from_vcard_with_uid (vcard, uid);
- list = g_slist_prepend (list, contact);
- }
+ /* array contains UIDs only */
+ if (client_view->priv->direct_book != NULL) {
+ direct_contacts_fetch (
+ client_view, vcards, OBJECTS_MODIFIED);
+ g_object_unref (client_view);
+ return;
+ }
+
+ /* array contains both UID and vcard */
+ for (ii = 0; vcards[ii] != NULL && vcards[ii + 1] != NULL; ii += 2) {
+ EContact *contact;
+ const gchar *vcard = vcards[ii];
+ const gchar *uid = vcards[ii + 1];
+
+ contact = e_contact_new_from_vcard_with_uid (vcard, uid);
+ list = g_slist_prepend (list, contact);
+ }
+
+ list = g_slist_reverse (list);
- list = g_slist_reverse (list);
+ /* Takes ownership of the linked list. */
+ book_client_view_emit_objects_modified (client_view, list);
- /* Takes ownership of the linked list. */
- book_client_view_emit_objects_modified (client_view, list);
+ g_object_unref (client_view);
+ }
}
static void
book_client_view_objects_removed_cb (EGdbusBookView *object,
const gchar * const *ids,
- EBookClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
- GSList *list = NULL;
- gint ii;
+ EBookClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- for (ii = 0; ids[ii] != NULL; ii++)
- list = g_slist_prepend (list, g_strdup (ids[ii]));
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
+ GSList *list = NULL;
+ gint ii;
+
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_set (&signal_closure->client_view, client_view);
- signal_closure->string_list = g_slist_reverse (list);
+ for (ii = 0; ids[ii] != NULL; ii++)
+ list = g_slist_prepend (list, g_strdup (ids[ii]));
- main_context = book_client_view_ref_main_context (client_view);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ signal_closure->string_list = g_slist_reverse (list);
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- book_client_view_emit_objects_removed_idle_cb,
- signal_closure,
- (GDestroyNotify) signal_closure_free);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
+ main_context = book_client_view_ref_main_context (client_view);
- g_main_context_unref (main_context);
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (
+ idle_source,
+ book_client_view_emit_objects_removed_idle_cb,
+ signal_closure,
+ (GDestroyNotify) signal_closure_free);
+ g_source_attach (idle_source, main_context);
+ g_source_unref (idle_source);
+
+ g_main_context_unref (main_context);
+
+ g_object_unref (client_view);
+ }
}
static void
book_client_view_progress_cb (EGdbusBookView *object,
guint percent,
const gchar *message,
- EBookClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ EBookClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_set (&signal_closure->client_view, client_view);
- signal_closure->message = g_strdup (message);
- signal_closure->percent = percent;
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- main_context = book_client_view_ref_main_context (client_view);
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- book_client_view_emit_progress_idle_cb,
- signal_closure,
- (GDestroyNotify) signal_closure_free);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ signal_closure->message = g_strdup (message);
+ signal_closure->percent = percent;
- g_main_context_unref (main_context);
+ main_context = book_client_view_ref_main_context (client_view);
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (
+ idle_source,
+ book_client_view_emit_progress_idle_cb,
+ signal_closure,
+ (GDestroyNotify) signal_closure_free);
+ g_source_attach (idle_source, main_context);
+ g_source_unref (idle_source);
+
+ g_main_context_unref (main_context);
+
+ g_object_unref (client_view);
+ }
}
static void
book_client_view_complete_cb (EGdbusBookView *object,
const gchar * const *in_error_strv,
- EBookClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ EBookClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_set (&signal_closure->client_view, client_view);
- e_gdbus_templates_decode_error (in_error_strv, &signal_closure->error);
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- main_context = book_client_view_ref_main_context (client_view);
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- book_client_view_emit_complete_idle_cb,
- signal_closure,
- (GDestroyNotify) signal_closure_free);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ e_gdbus_templates_decode_error (
+ in_error_strv, &signal_closure->error);
- g_main_context_unref (main_context);
+ main_context = book_client_view_ref_main_context (client_view);
+
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (
+ idle_source,
+ book_client_view_emit_complete_idle_cb,
+ signal_closure,
+ (GDestroyNotify) signal_closure_free);
+ g_source_attach (idle_source, main_context);
+ g_source_unref (idle_source);
+
+ g_main_context_unref (main_context);
- client_view->priv->complete = TRUE;
+ client_view->priv->complete = TRUE;
+
+ g_object_unref (client_view);
+ }
}
static void
@@ -805,29 +878,39 @@ book_client_view_initable_init (GInitable *initable,
priv->dbus_proxy = G_DBUS_PROXY (gdbus_bookview);
- handler_id = g_signal_connect (
+ handler_id = g_signal_connect_data (
priv->dbus_proxy, "objects-added",
- G_CALLBACK (book_client_view_objects_added_cb), initable);
+ G_CALLBACK (book_client_view_objects_added_cb),
+ weak_ref_new (initable),
+ (GClosureNotify) weak_ref_free, 0);
priv->objects_added_handler_id = handler_id;
- handler_id = g_signal_connect (
+ handler_id = g_signal_connect_data (
priv->dbus_proxy, "objects-modified",
- G_CALLBACK (book_client_view_objects_modified_cb), initable);
+ G_CALLBACK (book_client_view_objects_modified_cb),
+ weak_ref_new (initable),
+ (GClosureNotify) weak_ref_free, 0);
priv->objects_modified_handler_id = handler_id;
- handler_id = g_signal_connect (
+ handler_id = g_signal_connect_data (
priv->dbus_proxy, "objects-removed",
- G_CALLBACK (book_client_view_objects_removed_cb), initable);
+ G_CALLBACK (book_client_view_objects_removed_cb),
+ weak_ref_new (initable),
+ (GClosureNotify) weak_ref_free, 0);
priv->objects_removed_handler_id = handler_id;
- handler_id = g_signal_connect (
+ handler_id = g_signal_connect_data (
priv->dbus_proxy, "progress",
- G_CALLBACK (book_client_view_progress_cb), initable);
+ G_CALLBACK (book_client_view_progress_cb),
+ weak_ref_new (initable),
+ (GClosureNotify) weak_ref_free, 0);
priv->progress_handler_id = handler_id;
- handler_id = g_signal_connect (
+ handler_id = g_signal_connect_data (
priv->dbus_proxy, "complete",
- G_CALLBACK (book_client_view_complete_cb), initable);
+ G_CALLBACK (book_client_view_complete_cb),
+ weak_ref_new (initable),
+ (GClosureNotify) weak_ref_free, 0);
priv->complete_handler_id = handler_id;
/* When in direct read access mode, we add a special field
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]