[glib: 1/2] application: Unset the registered state after shutting down




commit 63873c0eb114faf6696874fe577912af687d67cf
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Wed Apr 21 06:17:36 2021 +0200

    application: Unset the registered state after shutting down
    
    An application that has been shut down is still marked as registered
    even if its implementation has been already destroyed.
    
    This may lead to unguarded crashes when calling functions that have
    assumptions for being used with registered applications.
    
    So, when an application is registered, mark it as unregistered just
    before destroying its implementation and after being shut down, so that
    we follow the registration process in reversed order.
    
    Added tests

 gio/gapplication.c       |  7 +++++
 gio/tests/gapplication.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)
---
diff --git a/gio/gapplication.c b/gio/gapplication.c
index 8e6517635..bf4a4cb65 100644
--- a/gio/gapplication.c
+++ b/gio/gapplication.c
@@ -2578,6 +2578,13 @@ g_application_run (GApplication  *application,
 
   if (application->priv->impl)
     {
+      if (application->priv->is_registered)
+        {
+          application->priv->is_registered = FALSE;
+
+          g_object_notify (G_OBJECT (application), "is-registered");
+        }
+
       g_application_impl_flush (application->priv->impl);
       g_application_impl_destroy (application->priv->impl);
       application->priv->impl = NULL;
diff --git a/gio/tests/gapplication.c b/gio/tests/gapplication.c
index 900e7ac97..6f1a27e0f 100644
--- a/gio/tests/gapplication.c
+++ b/gio/tests/gapplication.c
@@ -576,6 +576,81 @@ test_quit (void)
   g_free (binpath);
 }
 
+typedef struct
+{
+  gboolean shutdown;
+  GParamSpec *notify_spec; /* (owned) (nullable) */
+} RegisteredData;
+
+static void
+on_registered_shutdown (GApplication *app,
+                        gpointer user_data)
+{
+  RegisteredData *registered_data = user_data;
+
+  registered_data->shutdown = TRUE;
+}
+
+static void
+on_registered_notify (GApplication *app,
+                      GParamSpec *spec,
+                      gpointer user_data)
+{
+  RegisteredData *registered_data = user_data;
+  registered_data->notify_spec = g_param_spec_ref (spec);
+
+  if (g_application_get_is_registered (app))
+    g_assert_false (registered_data->shutdown);
+  else
+    g_assert_true (registered_data->shutdown);
+}
+
+static void
+test_registered (void)
+{
+  char *binpath = g_test_build_filename (G_TEST_BUILT, "unimportant", NULL);
+  gchar *argv[] = { binpath, NULL };
+  RegisteredData registered_data = { FALSE, NULL };
+  GApplication *app;
+
+  app = g_application_new (NULL, G_APPLICATION_FLAGS_NONE);
+  g_signal_connect (app, "activate", G_CALLBACK (noappid_activate), NULL);
+  g_signal_connect (app, "shutdown", G_CALLBACK (on_registered_shutdown), &registered_data);
+  g_signal_connect (app, "notify::is-registered", G_CALLBACK (on_registered_notify), &registered_data);
+
+  g_assert_null (registered_data.notify_spec);
+
+  g_assert_true (g_application_register (app, NULL, NULL));
+  g_assert_true (g_application_get_is_registered (app));
+
+  g_assert_nonnull (registered_data.notify_spec);
+  g_assert_cmpstr (registered_data.notify_spec->name, ==, "is-registered");
+  g_clear_pointer (&registered_data.notify_spec, g_param_spec_unref);
+
+  g_assert_false (registered_data.shutdown);
+
+  g_application_run (app, 1, argv);
+
+  g_assert_true (registered_data.shutdown);
+  g_assert_false (g_application_get_is_registered (app));
+  g_assert_nonnull (registered_data.notify_spec);
+  g_assert_cmpstr (registered_data.notify_spec->name, ==, "is-registered");
+  g_clear_pointer (&registered_data.notify_spec, g_param_spec_unref);
+
+  /* Register it again */
+  registered_data.shutdown = FALSE;
+  g_assert_true (g_application_register (app, NULL, NULL));
+  g_assert_true (g_application_get_is_registered (app));
+  g_assert_nonnull (registered_data.notify_spec);
+  g_assert_cmpstr (registered_data.notify_spec->name, ==, "is-registered");
+  g_clear_pointer (&registered_data.notify_spec, g_param_spec_unref);
+  g_assert_false (registered_data.shutdown);
+
+  g_object_unref (app);
+
+  g_free (binpath);
+}
+
 static void
 on_activate (GApplication *app)
 {
@@ -1136,6 +1211,7 @@ main (int argc, char **argv)
   g_test_add_func ("/gapplication/properties", properties);
   g_test_add_func ("/gapplication/app-id", appid);
   g_test_add_func ("/gapplication/quit", test_quit);
+  g_test_add_func ("/gapplication/registered", test_registered);
   g_test_add_func ("/gapplication/local-actions", test_local_actions);
 /*  g_test_add_func ("/gapplication/remote-actions", test_remote_actions); */
   g_test_add_func ("/gapplication/local-command-line", test_local_command_line);


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