[libpeas] Added peas_engine_shutdown()



commit 71bc92d78f70f83e52794a63da5144d3b0efe920
Author: Garrett Regier <alias301 gmail com>
Date:   Sun Feb 6 03:45:44 2011 -0800

    Added peas_engine_shutdown()
    
    It frees the memory the memory that is shared
    by PeasEngines.

 libpeas/peas-engine.c               |   49 +++++++++++++++++++++++++++++++++++
 libpeas/peas-engine.h               |    1 +
 peas-demo/peas-demo.c               |    6 +++-
 tests/libpeas-gtk/testing/testing.c |    2 +
 tests/libpeas/engine.c              |   45 ++++++++++++++++++++++++++++++++
 tests/libpeas/testing/testing.c     |    2 +
 6 files changed, 103 insertions(+), 2 deletions(-)
---
diff --git a/libpeas/peas-engine.c b/libpeas/peas-engine.c
index 99d150f..2258563 100644
--- a/libpeas/peas-engine.c
+++ b/libpeas/peas-engine.c
@@ -344,6 +344,13 @@ peas_engine_constructor (GType                  type,
       return NULL;
     }
 
+  if (shutdown)
+    {
+      g_warning ("libpeas cannot create a plugin engine "
+                 "as it has been shutdown.");
+      return NULL;
+    }
+
   if (default_engine != NULL)
     return g_object_ref (G_OBJECT (default_engine));
 
@@ -1168,3 +1175,45 @@ peas_engine_get_default (void)
 
   return default_engine;
 }
+
+static void
+destroy_loaders (void)
+{
+  g_hash_table_destroy (loaders);
+  loaders = NULL;
+}
+
+/**
+ * peas_engine_shutdown:
+ *
+ * Frees memory shared by PeasEngines.
+ * No libpeas API should be called after calling this.
+ */
+void
+peas_engine_shutdown (void)
+{
+  if (shutdown)
+    return;
+
+  shutdown = TRUE;
+
+  if (default_engine != NULL)
+    {
+      /* Add a weak ref that will destroy the loaders hashtable,
+       * this way if the engine is still around it won't segfault
+       */
+      g_object_weak_ref (G_OBJECT (default_engine),
+                         (GWeakNotify) destroy_loaders, NULL);
+
+      g_object_unref (default_engine);
+
+      /* The weak-ref should set it to NULL */
+      if (default_engine != NULL)
+        {
+          default_engine = NULL;
+
+          g_warning ("libpeas failed to shutdown, "
+                     "the plugin engine was not freed.");
+        }
+    }
+}
diff --git a/libpeas/peas-engine.h b/libpeas/peas-engine.h
index df56800..27370ba 100644
--- a/libpeas/peas-engine.h
+++ b/libpeas/peas-engine.h
@@ -69,6 +69,7 @@ struct _PeasEngineClass {
 
 GType             peas_engine_get_type            (void) G_GNUC_CONST;
 PeasEngine       *peas_engine_get_default         (void);
+void              peas_engine_shutdown            (void);
 
 void              peas_engine_add_search_path     (PeasEngine      *engine,
                                                    const gchar     *module_dir,
diff --git a/peas-demo/peas-demo.c b/peas-demo/peas-demo.c
index 6420b07..3c11753 100644
--- a/peas-demo/peas-demo.c
+++ b/peas-demo/peas-demo.c
@@ -59,7 +59,7 @@ create_main_window (void)
   GtkWidget *button;
 
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+  g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
   gtk_container_set_border_width (GTK_CONTAINER (window), 6);
   gtk_window_set_title (GTK_WINDOW (window), "Peas Demo");
 
@@ -138,7 +138,9 @@ main (int    argc,
 
   gtk_main ();
 
-  g_object_unref (engine);
+  gtk_widget_destroy (main_window);
+
+  peas_engine_shutdown ();
 
   return 0;
 }
diff --git a/tests/libpeas-gtk/testing/testing.c b/tests/libpeas-gtk/testing/testing.c
index a2a850d..549fadc 100644
--- a/tests/libpeas-gtk/testing/testing.c
+++ b/tests/libpeas-gtk/testing/testing.c
@@ -108,6 +108,8 @@ testing_engine_new (void)
       g_irepository_require (g_irepository_get_default (), "PeasGtk", "1.0", 0, &error);
       g_assert_no_error (error);
 
+      g_atexit (peas_engine_shutdown);
+
       initialized = TRUE;
     }
 
diff --git a/tests/libpeas/engine.c b/tests/libpeas/engine.c
index 07a526d..2751c2a 100644
--- a/tests/libpeas/engine.c
+++ b/tests/libpeas/engine.c
@@ -295,6 +295,48 @@ test_engine_disable_loader (PeasEngine *engine)
   g_test_trap_assert_stderr ("*Loader 'C' cannot be disabled*");
 }
 
+static void
+test_engine_shutdown (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+
+  /* Ref the engine to cause the shutdown to fail */
+  g_object_ref (engine);
+
+  /* libpeas fails to shutdown because the engine still has a ref */
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      peas_engine_shutdown ();
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*libpeas failed to shutdown*"
+                             "*plugin engine was not freed*");
+
+  /* Make sure that if an engine is around
+   * after shutdown the engine does not segfault.
+   */
+  info = peas_engine_get_plugin_info (engine, "loadable");
+  g_assert (peas_engine_load_plugin (engine, info));
+
+  /* Free our extra ref and then the engine */
+  g_object_unref (engine);
+  testing_engine_free (engine);
+
+  /* Should be able to shutdown multiple times */
+  peas_engine_shutdown ();
+
+  /* Cannot get the default as libpeas has been shutdown */
+  if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT | G_TEST_TRAP_SILENCE_STDERR))
+    {
+      peas_engine_get_default ();
+      exit (0);
+    }
+  g_test_trap_assert_failed ();
+  g_test_trap_assert_stderr ("*libpeas cannot create a plugin "
+                              "engine as it has been shutdown*");
+}
+
 int
 main (int    argc,
       char **argv)
@@ -326,6 +368,9 @@ main (int    argc,
   TEST ("invalid-loader", invalid_loader);
   TEST ("disable-loader", disable_loader);
 
+  /* MUST be last */
+  TEST ("shutdown", shutdown);
+
 #undef TEST
 
   return g_test_run ();
diff --git a/tests/libpeas/testing/testing.c b/tests/libpeas/testing/testing.c
index fbccbe0..c29e122 100644
--- a/tests/libpeas/testing/testing.c
+++ b/tests/libpeas/testing/testing.c
@@ -116,6 +116,8 @@ testing_engine_new (void)
                                      "Introspection", "1.0", 0, &error);
       g_assert_no_error (error);
 
+      g_atexit (peas_engine_shutdown);
+
       initialized = TRUE;
     }
 



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