[evolution-data-server] ECalClientView: Make D-Bus signal handlers thread-safe.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] ECalClientView: Make D-Bus signal handlers thread-safe.
- Date: Sat, 4 May 2013 16:58:53 +0000 (UTC)
commit b255406dd249327efdb133e2c797b4dd496c736b
Author: Matthew Barnes <mbarnes redhat com>
Date: Sat May 4 09:44:00 2013 -0400
ECalClientView: Make D-Bus signal handlers thread-safe.
Seeing crashes now where handler functions for D-Bus signals like
"objects-added" are receiving finalized ECalClientView 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.
calendar/libecal/e-cal-client-view.c | 293 ++++++++++++++++++----------------
1 files changed, 152 insertions(+), 141 deletions(-)
---
diff --git a/calendar/libecal/e-cal-client-view.c b/calendar/libecal/e-cal-client-view.c
index c31e9fc..e37f15b 100644
--- a/calendar/libecal/e-cal-client-view.c
+++ b/calendar/libecal/e-cal-client-view.c
@@ -295,203 +295,204 @@ cal_client_view_emit_complete_idle_cb (gpointer user_data)
static void
cal_client_view_objects_added_cb (EGdbusCalView *dbus_proxy,
const gchar * const *objects,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- ECalClient *client;
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- client = e_cal_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 ECalClient 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->component_list = build_object_list (objects);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ signal_closure->component_list = build_object_list (objects);
- main_context = cal_client_view_ref_main_context (client_view);
+ main_context = cal_client_view_ref_main_context (client_view);
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- cal_client_view_emit_objects_added_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,
+ cal_client_view_emit_objects_added_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
cal_client_view_objects_modified_cb (EGdbusCalView *dbus_proxy,
const gchar * const *objects,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- ECalClient *client;
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- client = e_cal_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 ECalClient 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->component_list = build_object_list (objects);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ signal_closure->component_list = build_object_list (objects);
- main_context = cal_client_view_ref_main_context (client_view);
+ main_context = cal_client_view_ref_main_context (client_view);
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- cal_client_view_emit_objects_modified_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,
+ cal_client_view_emit_objects_modified_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
cal_client_view_objects_removed_cb (EGdbusCalView *dbus_proxy,
const gchar * const *uids,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- ECalClient *client;
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- client = e_cal_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 ECalClient 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->component_id_list = build_id_list (uids);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ signal_closure->component_id_list = build_id_list (uids);
- main_context = cal_client_view_ref_main_context (client_view);
+ main_context = cal_client_view_ref_main_context (client_view);
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- cal_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,
+ cal_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
cal_client_view_progress_cb (EGdbusCalView *dbus_proxy,
guint percent,
const gchar *message,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- ECalClient *client;
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- client = e_cal_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 ECalClient 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 = cal_client_view_ref_main_context (client_view);
+ main_context = cal_client_view_ref_main_context (client_view);
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- cal_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,
+ cal_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
cal_client_view_complete_cb (EGdbusCalView *dbus_proxy,
const gchar * const *arg_error,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- ECalClient *client;
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
- if (!client_view->priv->running)
- return;
+ client_view = g_weak_ref_get (client_view_weak_ref);
- client = e_cal_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 ECalClient 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 (arg_error, &signal_closure->error);
+ signal_closure = g_slice_new0 (SignalClosure);
+ g_weak_ref_set (&signal_closure->client_view, client_view);
+ e_gdbus_templates_decode_error (
+ arg_error, &signal_closure->error);
- main_context = cal_client_view_ref_main_context (client_view);
+ main_context = cal_client_view_ref_main_context (client_view);
- idle_source = g_idle_source_new ();
- g_source_set_callback (
- idle_source,
- cal_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,
+ cal_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);
- g_object_unref (client);
+ g_object_unref (client_view);
+ }
}
static void
@@ -688,29 +689,39 @@ cal_client_view_initable_init (GInitable *initable,
priv->dbus_proxy = G_DBUS_PROXY (gdbus_calview);
- handler_id = g_signal_connect (
+ handler_id = g_signal_connect_data (
priv->dbus_proxy, "objects-added",
- G_CALLBACK (cal_client_view_objects_added_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_objects_modified_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_objects_removed_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_progress_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_complete_cb), initable);
+ G_CALLBACK (cal_client_view_complete_cb),
+ e_weak_ref_new (initable),
+ (GClosureNotify) e_weak_ref_free, 0);
priv->complete_handler_id = handler_id;
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]