[evolution-data-server/gnome-3-8] 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/gnome-3-8] ECalClientView: Make D-Bus signal handlers thread-safe.
- Date: Sat, 4 May 2013 16:59:00 +0000 (UTC)
commit 092aa3f08d97f85503b662056b12ad0847579924
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.
(cherry picked from commit b255406dd249327efdb133e2c797b4dd496c736b)
Conflicts:
calendar/libecal/e-cal-client-view.c
calendar/libecal/e-cal-client-view.c | 291 +++++++++++++++++++++------------
1 files changed, 185 insertions(+), 106 deletions(-)
---
diff --git a/calendar/libecal/e-cal-client-view.c b/calendar/libecal/e-cal-client-view.c
index 8db2b05..e688a11 100644
--- a/calendar/libecal/e-cal-client-view.c
+++ b/calendar/libecal/e-cal-client-view.c
@@ -117,6 +117,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 *
cal_client_view_ref_main_context (ECalClientView *client_view)
{
@@ -297,153 +315,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)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
+
+ client_view = g_weak_ref_get (client_view_weak_ref);
- if (!client_view->priv->running)
- return;
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- signal_closure = g_slice_new0 (SignalClosure);
- g_weak_ref_set (&signal_closure->client_view, client_view);
- signal_closure->component_list = build_object_list (objects);
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- main_context = cal_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->component_list = build_object_list (objects);
- 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);
+ main_context = cal_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,
+ 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_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)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
+
+ client_view = g_weak_ref_get (client_view_weak_ref);
+
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- if (!client_view->priv->running)
- 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_view);
+ }
}
static void
cal_client_view_objects_removed_cb (EGdbusCalView *dbus_proxy,
const gchar * const *uids,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
+
+ client_view = g_weak_ref_get (client_view_weak_ref);
+
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- if (!client_view->priv->running)
- 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_view);
+ }
}
static void
cal_client_view_progress_cb (EGdbusCalView *dbus_proxy,
guint percent,
const gchar *message,
- ECalClientView *client_view)
+ GWeakRef *client_view_weak_ref)
{
- 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);
- 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 = cal_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,
- 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);
+ 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 = 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);
+
+ g_main_context_unref (main_context);
+
+ 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)
{
- GSource *idle_source;
- GMainContext *main_context;
- SignalClosure *signal_closure;
+ ECalClientView *client_view;
+
+ client_view = g_weak_ref_get (client_view_weak_ref);
- if (!client_view->priv->running)
- return;
+ if (client_view != NULL) {
+ GSource *idle_source;
+ GMainContext *main_context;
+ SignalClosure *signal_closure;
- 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);
+ if (!client_view->priv->running) {
+ g_object_unref (client_view);
+ return;
+ }
- main_context = cal_client_view_ref_main_context (client_view);
+ 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);
- 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);
+ main_context = cal_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,
+ 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_object_unref (client_view);
+ }
}
static void
@@ -644,29 +713,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),
+ 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 (cal_client_view_objects_modified_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_objects_removed_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_progress_cb), initable);
+ G_CALLBACK (cal_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 (cal_client_view_complete_cb), initable);
+ G_CALLBACK (cal_client_view_complete_cb),
+ weak_ref_new (initable),
+ (GClosureNotify) 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]