[evolution-data-server] 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] EBookClientView: Make D-Bus signal handlers thread-safe.
- Date: Sat, 4 May 2013 16:58:48 +0000 (UTC)
commit 2df7a66eb535863dc41db446afc67ca4e0268c12
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.
addressbook/libebook/e-book-client-view.c | 327 +++++++++++++++--------------
1 files changed, 171 insertions(+), 156 deletions(-)
---
diff --git a/addressbook/libebook/e-book-client-view.c b/addressbook/libebook/e-book-client-view.c
index 86592a2..ce85774 100644
--- a/addressbook/libebook/e-book-client-view.c
+++ b/addressbook/libebook/e-book-client-view.c
@@ -257,18 +257,10 @@ static void
book_client_view_emit_objects_added (EBookClientView *client_view,
GSList *object_list)
{
- EBookClient *client;
GSource *idle_source;
GMainContext *main_context;
SignalClosure *signal_closure;
- client = e_book_client_view_ref_client (client_view);
-
- /* Suppress any further signal emissions if
- * our EBookClient has already been finalized. */
- if (client == NULL)
- return;
-
signal_closure = g_slice_new0 (SignalClosure);
g_weak_ref_set (&signal_closure->client_view, client_view);
signal_closure->object_list = object_list; /* takes ownership */
@@ -285,26 +277,16 @@ book_client_view_emit_objects_added (EBookClientView *client_view,
g_source_unref (idle_source);
g_main_context_unref (main_context);
-
- g_object_unref (client);
}
static void
book_client_view_emit_objects_modified (EBookClientView *client_view,
GSList *object_list)
{
- EBookClient *client;
GSource *idle_source;
GMainContext *main_context;
SignalClosure *signal_closure;
- client = e_book_client_view_ref_client (client_view);
-
- /* Suppress any further signal emissions if
- * our EBookClient has already been finalized. */
- if (client == NULL)
- return;
-
signal_closure = g_slice_new0 (SignalClosure);
g_weak_ref_set (&signal_closure->client_view, client_view);
signal_closure->object_list = object_list; /* takes ownership */
@@ -321,8 +303,6 @@ book_client_view_emit_objects_modified (EBookClientView *client_view,
g_source_unref (idle_source);
g_main_context_unref (main_context);
-
- g_object_unref (client);
}
static gchar *
@@ -461,196 +441,221 @@ direct_contacts_fetch (EBookClientView *client_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_backend != 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_backend != 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];
+
+ 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);
- /* 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_backend != 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_backend != NULL) {
+ direct_contacts_fetch (
+ client_view, vcards, OBJECTS_MODIFIED);
+ 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];
+
+ 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_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)
{
- EBookClient *client;
- 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);
- client = e_book_client_view_ref_client (client_view);
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
+ GSList *list = NULL;
+ gint ii;
- /* Suppress any further signal emissions if
- * our EBookClient has already been finalized. */
- if (client == NULL)
- return;
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- for (ii = 0; ids[ii] != NULL; ii++)
- list = g_slist_prepend (list, g_strdup (ids[ii]));
+ for (ii = 0; ids[ii] != NULL; ii++)
+ list = g_slist_prepend (list, g_strdup (ids[ii]));
- signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_set (&signal_closure->client_view, client_view);
- signal_closure->string_list = g_slist_reverse (list);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ signal_closure->string_list = g_slist_reverse (list);
- main_context = book_client_view_ref_main_context (client_view);
+ 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_objects_removed_idle_cb,
- signal_closure,
- (GDestroyNotify) signal_closure_free);
- g_source_attach (idle_source, main_context);
- g_source_unref (idle_source);
+ 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_main_context_unref (main_context);
- g_object_unref (client);
+ 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)
{
- EBookClient *client;
- 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);
- client = e_book_client_view_ref_client (client_view);
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- /* Suppress any further signal emissions if
- * our EBookClient has already been finalized. */
- if (client == NULL)
- return;
+ 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->message = g_strdup (message);
- signal_closure->percent = percent;
+ 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;
- main_context = book_client_view_ref_main_context (client_view);
+ 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);
+ 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_main_context_unref (main_context);
- g_object_unref (client);
+ 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)
{
- EBookClient *client;
- 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);
- client = e_book_client_view_ref_client (client_view);
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- /* Suppress any further signal emissions if
- * our EBookClient has already been finalized. */
- if (client == NULL)
- return;
+ 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);
- e_gdbus_templates_decode_error (in_error_strv, &signal_closure->error);
+ 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);
- main_context = book_client_view_ref_main_context (client_view);
+ 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);
+ 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);
+ g_main_context_unref (main_context);
- client_view->priv->complete = TRUE;
+ client_view->priv->complete = TRUE;
- g_object_unref (client);
+ g_object_unref (client_view);
+ }
}
static void
@@ -871,29 +876,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),
+ e_weak_ref_new (initable),
+ (GClosureNotify) e_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),
+ e_weak_ref_new (initable),
+ (GClosureNotify) e_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),
+ e_weak_ref_new (initable),
+ (GClosureNotify) e_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),
+ e_weak_ref_new (initable),
+ (GClosureNotify) e_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),
+ e_weak_ref_new (initable),
+ (GClosureNotify) e_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]