[evolution] Use GWeakRef when watching D-Bus bus names



commit 07a2087169e31d9a6c1694ae59c7f1d354b8ef6b
Author: Milan Crha <mcrha redhat com>
Date:   Thu Feb 21 14:56:38 2019 +0100

    Use GWeakRef when watching D-Bus bus names
    
    With certain operations interleaving the callback to name-appeared
    signal could be called after the object in the user_data had been freed.
    Even when the free of the object unwatches the D-Bus name, it's too
    late, because the signal callback is already scheduled in the main loop.
    
    Reported downstream at:
    https://bugzilla.redhat.com/show_bug.cgi?id=1677846

 src/modules/itip-formatter/itip-view.c      | 105 +++++++++++++++++-----------
 src/modules/webkit-editor/e-webkit-editor.c |  47 ++++++++++---
 2 files changed, 104 insertions(+), 48 deletions(-)
---
diff --git a/src/modules/itip-formatter/itip-view.c b/src/modules/itip-formatter/itip-view.c
index fa255a992d..7849b8d9e9 100644
--- a/src/modules/itip-formatter/itip-view.c
+++ b/src/modules/itip-formatter/itip-view.c
@@ -1821,57 +1821,75 @@ itip_view_write_for_printing (ItipView *view,
 static void
 web_extension_proxy_created_cb (GDBusProxy *proxy,
                                 GAsyncResult *result,
-                                ItipView *view)
+                                GWeakRef *view_wr)
 {
+       ItipView *view;
        GError *error = NULL;
 
-       view->priv->web_extension = g_dbus_proxy_new_finish (result, &error);
-       if (!view->priv->web_extension) {
-               g_warning ("Error creating web extension proxy: %s\n", error->message);
-               g_error_free (error);
+       view = g_weak_ref_get (view_wr);
+
+       if (!view) {
+               e_weak_ref_free (view_wr);
+               return;
        }
 
-       view->priv->web_extension_source_changed_cb_signal_id =
-               g_dbus_connection_signal_subscribe (
-                       g_dbus_proxy_get_connection (view->priv->web_extension),
-                       g_dbus_proxy_get_name (view->priv->web_extension),
-                       MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-                       "SourceChanged",
-                       MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-                       NULL,
-                       G_DBUS_SIGNAL_FLAGS_NONE,
-                       source_changed_cb_signal_cb,
-                       view,
-                       NULL);
+       view->priv->web_extension = g_dbus_proxy_new_finish (result, &error);
+       if (!view->priv->web_extension) {
+               g_warning ("Error creating web extension proxy: %s\n", error ? error->message : "Unknown 
error");
+               g_clear_error (&error);
+       } else {
+               view->priv->web_extension_source_changed_cb_signal_id =
+                       g_dbus_connection_signal_subscribe (
+                               g_dbus_proxy_get_connection (view->priv->web_extension),
+                               g_dbus_proxy_get_name (view->priv->web_extension),
+                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
+                               "SourceChanged",
+                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
+                               NULL,
+                               G_DBUS_SIGNAL_FLAGS_NONE,
+                               source_changed_cb_signal_cb,
+                               view,
+                               NULL);
+
+               view->priv->web_extension_recur_toggled_signal_id =
+                       g_dbus_connection_signal_subscribe (
+                               g_dbus_proxy_get_connection (view->priv->web_extension),
+                               g_dbus_proxy_get_name (view->priv->web_extension),
+                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
+                               "RecurToggled",
+                               MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
+                               NULL,
+                               G_DBUS_SIGNAL_FLAGS_NONE,
+                               (GDBusSignalCallback) recur_toggled_signal_cb,
+                               view,
+                               NULL);
 
-       view->priv->web_extension_recur_toggled_signal_id =
-               g_dbus_connection_signal_subscribe (
-                       g_dbus_proxy_get_connection (view->priv->web_extension),
-                       g_dbus_proxy_get_name (view->priv->web_extension),
-                       MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
-                       "RecurToggled",
-                       MODULE_ITIP_FORMATTER_WEB_EXTENSION_OBJECT_PATH,
-                       NULL,
-                       G_DBUS_SIGNAL_FLAGS_NONE,
-                       (GDBusSignalCallback) recur_toggled_signal_cb,
-                       view,
+               e_util_invoke_g_dbus_proxy_call_with_error_check (
+                       view->priv->web_extension,
+                       "CreateDOMBindings",
+                       g_variant_new ("(ts)", view->priv->page_id, view->priv->part_id),
                        NULL);
-
-       e_util_invoke_g_dbus_proxy_call_with_error_check (
-               view->priv->web_extension,
-               "CreateDOMBindings",
-               g_variant_new ("(ts)", view->priv->page_id, view->priv->part_id),
-               NULL);
+       }
 
        itip_view_init_view (view);
+
+       e_weak_ref_free (view_wr);
+       g_object_unref (view);
 }
 
 static void
 web_extension_appeared_cb (GDBusConnection *connection,
                            const gchar *name,
                            const gchar *name_owner,
-                           ItipView *view)
+                           GWeakRef *view_wr)
 {
+       ItipView *view;
+
+       view = g_weak_ref_get (view_wr);
+
+       if (!view)
+               return;
+
        g_dbus_proxy_new (
                connection,
                G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
@@ -1883,15 +1901,24 @@ web_extension_appeared_cb (GDBusConnection *connection,
                MODULE_ITIP_FORMATTER_WEB_EXTENSION_INTERFACE,
                NULL,
                (GAsyncReadyCallback)web_extension_proxy_created_cb,
-               view);
+               e_weak_ref_new (view));
+
+       g_object_unref (view);
 }
 
 static void
 web_extension_vanished_cb (GDBusConnection *connection,
                            const gchar *name,
-                           ItipView *view)
+                           GWeakRef *view_wr)
 {
-       g_clear_object (&view->priv->web_extension);
+       ItipView *view;
+
+       view = g_weak_ref_get (view_wr);
+
+       if (view) {
+               g_clear_object (&view->priv->web_extension);
+               g_object_unref (view);
+       }
 }
 
 static void
@@ -1904,7 +1931,7 @@ itip_view_watch_web_extension (ItipView *view)
                        G_BUS_NAME_WATCHER_FLAGS_NONE,
                        (GBusNameAppearedCallback) web_extension_appeared_cb,
                        (GBusNameVanishedCallback) web_extension_vanished_cb,
-                       view, NULL);
+                       e_weak_ref_new (view), (GDestroyNotify) e_weak_ref_free);
 }
 
 GDBusProxy *
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index 33af2bd663..5510608da3 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -530,14 +530,22 @@ dispatch_pending_operations (EWebKitEditor *wk_editor)
 static void
 web_extension_proxy_created_cb (GDBusProxy *proxy,
                                 GAsyncResult *result,
-                                EWebKitEditor *wk_editor)
+                                GWeakRef *wk_editor_rf)
 {
+       EWebKitEditor *wk_editor;
        GError *error = NULL;
 
+       wk_editor = g_weak_ref_get (wk_editor_rf);
+
+       if (!wk_editor) {
+               e_weak_ref_free (wk_editor_rf);
+               return;
+       }
+
        wk_editor->priv->web_extension = g_dbus_proxy_new_finish (result, &error);
        if (!wk_editor->priv->web_extension) {
-               g_warning ("Error creating web extension proxy: %s\n", error->message);
-               g_error_free (error);
+               g_warning ("Error creating web extension proxy: %s\n", error ? error->message : "Unknown 
error");
+               g_clear_error (&error);
 
                if (wk_editor->priv->initialized_callback) {
                        wk_editor->priv->initialized_callback (E_CONTENT_EDITOR (wk_editor), 
wk_editor->priv->initialized_user_data);
@@ -546,6 +554,9 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                        wk_editor->priv->initialized_user_data = NULL;
                }
 
+               e_weak_ref_free (wk_editor_rf);
+               g_object_unref (wk_editor);
+
                return;
        }
 
@@ -628,14 +639,24 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
                wk_editor->priv->initialized_callback = NULL;
                wk_editor->priv->initialized_user_data = NULL;
        }
+
+       e_weak_ref_free (wk_editor_rf);
+       g_object_unref (wk_editor);
 }
 
 static void
 web_extension_appeared_cb (GDBusConnection *connection,
                            const gchar *name,
                            const gchar *name_owner,
-                           EWebKitEditor *wk_editor)
+                           GWeakRef *wk_editor_wr)
 {
+       EWebKitEditor *wk_editor;
+
+       wk_editor = g_weak_ref_get (wk_editor_wr);
+
+       if (!wk_editor)
+               return;
+
        g_dbus_proxy_new (
                connection,
                G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START |
@@ -646,15 +667,22 @@ web_extension_appeared_cb (GDBusConnection *connection,
                E_WEBKIT_EDITOR_WEB_EXTENSION_INTERFACE,
                NULL,
                (GAsyncReadyCallback) web_extension_proxy_created_cb,
-               wk_editor);
+               e_weak_ref_new (wk_editor));
+
+       g_object_unref (wk_editor);
 }
 
 static void
 web_extension_vanished_cb (GDBusConnection *connection,
                            const gchar *name,
-                           EWebKitEditor *wk_editor)
+                           GWeakRef *wk_editor_wr)
 {
-       g_return_if_fail (E_IS_WEBKIT_EDITOR (wk_editor));
+       EWebKitEditor *wk_editor;
+
+       wk_editor = g_weak_ref_get (wk_editor_wr);
+
+       if (!wk_editor)
+               return;
 
        /* The vanished callback can be sometimes called before the appeared
           callback, in which case it doesn't make sense to unwatch the name. */
@@ -666,6 +694,8 @@ web_extension_vanished_cb (GDBusConnection *connection,
                        wk_editor->priv->web_extension_watch_name_id = 0;
                }
        }
+
+       g_object_unref (wk_editor);
 }
 
 static void
@@ -682,8 +712,7 @@ webkit_editor_watch_web_extension (EWebKitEditor *wk_editor)
                        G_BUS_NAME_WATCHER_FLAGS_NONE,
                        (GBusNameAppearedCallback) web_extension_appeared_cb,
                        (GBusNameVanishedCallback) web_extension_vanished_cb,
-                       wk_editor,
-                       NULL);
+                       e_weak_ref_new (wk_editor), (GDestroyNotify) e_weak_ref_free);
 
        g_free (service_name);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]