From c5748328bee08e322997cc4703c372f6866a1693 Mon Sep 17 00:00:00 2001 From: Cosimo Cecchi Date: Fri, 13 Sep 2013 11:38:47 -0700 Subject: [PATCH] gapplication: don't rely on cmdline being finalized immediately The GApplicationCommandLine DBus implementation currently calls g_dbus_method_invocation_return_value() in its finalize() implementation only, relying on the object being destroyed after g_object_unref() is called on it inside g_application_impl_method_call(). While this is usually fine for C applications, when overriding the command_line vfunc from language bindings, the binding might add extra references to the object, which might not be released immediately - e.g. because they're garbage collected, or possibly even leaked. The same scenario could happen in a C application that decides to keep a reference to the passed-in GApplicationCommandLine object. To ensure the CommandLine DBus method always gets a reply after the invocation of command_line in the primary instance, explicitly send the message back before dropping our reference to the object. https://bugzilla.gnome.org/show_bug.cgi?id=708042 --- gio/gapplicationimpl-dbus.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c index d15e643..5c948cc 100644 --- a/gio/gapplicationimpl-dbus.c +++ b/gio/gapplicationimpl-dbus.c @@ -129,6 +129,9 @@ struct _GApplicationImpl static GApplicationCommandLine * g_dbus_command_line_new (GDBusMethodInvocation *invocation); +static void +g_dbus_command_line_return (GApplicationCommandLine *cmdline); + static GVariant * g_application_impl_get_property (GDBusConnection *connection, const gchar *sender, @@ -259,6 +262,8 @@ g_application_impl_method_call (GDBusConnection *connection, g_application_command_line_set_exit_status (cmdline, status); class->after_emit (impl->app, platform_data); g_variant_unref (platform_data); + + g_dbus_command_line_return (cmdline); g_object_unref (cmdline); } else if (g_str_equal (method_name, "ActivateAction")) @@ -787,6 +792,8 @@ typedef struct GDBusConnection *connection; const gchar *bus_name; const gchar *object_path; + + gboolean returned; } GDBusCommandLine; @@ -852,16 +859,29 @@ g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline) } static void -g_dbus_command_line_finalize (GObject *object) +g_dbus_command_line_return (GApplicationCommandLine *cmdline) { - GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); - GDBusCommandLine *gdbcl = (GDBusCommandLine *) object; + GDBusCommandLine *gdbcl = (GDBusCommandLine *) cmdline; gint status; + if (gdbcl->returned) + return; + + gdbcl->returned = TRUE; + status = g_application_command_line_get_exit_status (cmdline); g_dbus_method_invocation_return_value (gdbcl->invocation, g_variant_new ("(i)", status)); +} + +static void +g_dbus_command_line_finalize (GObject *object) +{ + GApplicationCommandLine *cmdline = G_APPLICATION_COMMAND_LINE (object); + GDBusCommandLine *gdbcl = (GDBusCommandLine *) object; + + g_dbus_command_line_return (cmdline); g_object_unref (gdbcl->invocation); G_OBJECT_CLASS (g_dbus_command_line_parent_class) -- 2.7.4