gnucash stable: Multiple changes pushed

Christopher Lam clam at code.gnucash.org
Mon Jul 3 20:11:56 EDT 2023


Updated	 via  https://github.com/Gnucash/gnucash/commit/59be6f49 (commit)
	 via  https://github.com/Gnucash/gnucash/commit/d287c301 (commit)
	from  https://github.com/Gnucash/gnucash/commit/b011c81b (commit)



commit 59be6f4974d7607cbf385378034e17ad493d0586
Merge: b011c81b62 d287c30145
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Tue Jul 4 08:10:53 2023 +0800

    Merge branch 'gsettings-cpp' into stable #1682
    
    plugs a runaway leak


commit d287c30145c2c026e1768ad8b7ae22740c0458c5
Author: Christopher Lam <christopher.lck at gmail.com>
Date:   Fri Jun 23 22:46:32 2023 +0800

    [gsettings.cpp] use std::unordered_map which releases on shutdown
    
    Better than a GHashTable schema_hash which is not being destroyed at shutdown

diff --git a/libgnucash/app-utils/gnc-gsettings.cpp b/libgnucash/app-utils/gnc-gsettings.cpp
index df26a0576d..668eb5928c 100644
--- a/libgnucash/app-utils/gnc-gsettings.cpp
+++ b/libgnucash/app-utils/gnc-gsettings.cpp
@@ -39,13 +39,26 @@
 #include <boost/property_tree/xml_parser.hpp>
 #include <fstream>
 #include <iostream>
+#include <unordered_map>
 
 namespace bpt = boost::property_tree;
 
 #define GSET_SCHEMA_PREFIX "org.gnucash.GnuCash"
 #define GSET_SCHEMA_OLD_PREFIX "org.gnucash"
 
-static GHashTable *schema_hash = nullptr;
+struct GSettingsDeleter
+{
+    void operator()(GSettings* gsp)
+    {
+        g_object_unref(gsp);
+    }
+};
+
+static GSettingsDeleter g_settings_deleter;
+
+using GSettingsPtr = std::unique_ptr<GSettings, GSettingsDeleter>;
+
+static std::unordered_map<std::string,GSettingsPtr> schema_hash;
 
 /* This static indicates the debugging module that this .o belongs to.  */
 static QofLogModule log_module = "gnc.app-utils.gsettings";
@@ -72,11 +85,25 @@ static bool gnc_gsettings_is_valid_key(GSettings *settings, const gchar *key)
     return found;
 }
 
+static std::string
+normalize_schema_name (const gchar *name)
+{
+    if (!name)
+        return GSET_SCHEMA_PREFIX;
+
+    if (g_str_has_prefix (name, GSET_SCHEMA_PREFIX) ||
+       (g_str_has_prefix (name, GSET_SCHEMA_OLD_PREFIX)))
+        return name;
+
+    return std::string{GSET_SCHEMA_PREFIX} + '.' + name;
+}
+
 static GSettings * gnc_gsettings_get_settings_obj (const gchar *schema_str)
 {
     ENTER("");
 
-    auto full_name = gnc_gsettings_normalize_schema_name (schema_str);
+    auto full_name_str = normalize_schema_name (schema_str);
+    auto full_name = full_name_str.c_str();
     auto schema_source {g_settings_schema_source_get_default()};
     auto schema {g_settings_schema_source_lookup(schema_source, full_name, true)};
     auto gset = g_settings_new_full (schema, nullptr, nullptr);
@@ -85,13 +112,33 @@ static GSettings * gnc_gsettings_get_settings_obj (const gchar *schema_str)
     if (!G_IS_SETTINGS(gset))
         PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name);
 
-    g_free(full_name);
-
     LEAVE("");
     g_settings_schema_unref (schema);
     return gset;
 }
 
+static GSettings*
+schema_to_gsettings (const char *schema, bool can_retrieve)
+{
+    auto full_name = normalize_schema_name (schema);
+    auto iter = schema_hash.find (full_name);
+    if (iter != schema_hash.end())
+        return iter->second.get();
+
+    if (!can_retrieve)
+        return nullptr;
+
+    auto gs_obj = gnc_gsettings_get_settings_obj (schema);
+    if (!G_IS_SETTINGS (gs_obj))
+    {
+        PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name.c_str());
+        return nullptr;
+    }
+
+    schema_hash[full_name] = GSettingsPtr (gs_obj, g_settings_deleter);
+    return gs_obj;
+}
+
 /************************************************************/
 /*                      GSettings Utilities                 */
 /************************************************************/
@@ -102,20 +149,6 @@ gnc_gsettings_get_prefix (void)
     return GSET_SCHEMA_PREFIX;
 }
 
-gchar *
-gnc_gsettings_normalize_schema_name (const gchar *name)
-{
-    if (!name)
-        return g_strdup(GSET_SCHEMA_PREFIX);
-
-    if (g_str_has_prefix (name, GSET_SCHEMA_PREFIX) ||
-       (g_str_has_prefix (name, GSET_SCHEMA_OLD_PREFIX)))
-        return g_strdup(name);
-
-    return g_strjoin(".", GSET_SCHEMA_PREFIX, name, nullptr);
-}
-
-
 /************************************************************/
 /*                   Change notification                    */
 /************************************************************/
@@ -128,20 +161,7 @@ gnc_gsettings_register_cb (const gchar *schema, const gchar *key,
     ENTER("");
     g_return_val_if_fail (func, 0);
 
-    if (!schema_hash)
-        schema_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-
-    auto full_name = gnc_gsettings_normalize_schema_name (schema);
-    auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
-    if (!gs_obj)
-    {
-        gs_obj = gnc_gsettings_get_settings_obj (schema);
-        if (G_IS_SETTINGS (gs_obj))
-            g_hash_table_insert (schema_hash, g_strdup (full_name), gs_obj);
-        else
-            PWARN ("Ignoring attempt to access unknown gsettings schema %s", full_name);
-    }
-    g_free (full_name);
+    auto gs_obj = schema_to_gsettings (schema, true);
     g_return_val_if_fail (G_IS_SETTINGS (gs_obj), 0);
 
     auto signal = static_cast<char *> (nullptr);
@@ -186,9 +206,7 @@ gnc_gsettings_remove_cb_by_func (const gchar *schema, const gchar *key,
     ENTER ();
     g_return_if_fail (func);
 
-    auto full_name = gnc_gsettings_normalize_schema_name (schema);
-    auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
-    g_free (full_name);
+    auto gs_obj = schema_to_gsettings (schema, false);
 
     if (!G_IS_SETTINGS (gs_obj))
     {
@@ -228,9 +246,7 @@ gnc_gsettings_remove_cb_by_id (const gchar *schema, guint handlerid)
 {
     ENTER ();
 
-    auto full_name = gnc_gsettings_normalize_schema_name (schema);
-    auto gs_obj = static_cast<GSettings*> (g_hash_table_lookup (schema_hash, full_name));
-    g_free (full_name);
+    auto gs_obj = schema_to_gsettings (schema, false);
 
     if (!G_IS_SETTINGS (gs_obj))
     {
@@ -297,7 +313,8 @@ gs_obj_unblock_handlers ([[maybe_unused]] gpointer key, gpointer gs_obj,
 void gnc_gsettings_block_all (void)
 {
     ENTER ();
-    g_hash_table_foreach (schema_hash, gs_obj_block_handlers, nullptr);
+    for (const auto& it : schema_hash)
+        gs_obj_block_handlers (nullptr, it.second.get(), nullptr);
     LEAVE();
 }
 
@@ -305,7 +322,8 @@ void gnc_gsettings_block_all (void)
 void gnc_gsettings_unblock_all (void)
 {
     ENTER ();
-    g_hash_table_foreach (schema_hash, gs_obj_unblock_handlers, nullptr);
+    for (const auto& it : schema_hash)
+        gs_obj_unblock_handlers (nullptr, it.second.get(), nullptr);
     LEAVE();
 }
 
diff --git a/libgnucash/app-utils/gnc-gsettings.h b/libgnucash/app-utils/gnc-gsettings.h
index 5e9704d123..bbd013a2b8 100644
--- a/libgnucash/app-utils/gnc-gsettings.h
+++ b/libgnucash/app-utils/gnc-gsettings.h
@@ -56,24 +56,6 @@
 extern "C" {
 #endif
 
-/** Convert a partial schema name into a complete gsettings schema name.
- *
- *  This function takes a partial gsettings schema name and converts
- *  it into a fully qualified gsettings schema name.  It does this
- *  by prepending the standard prefix for all gnucash schemas.
- *  If the schema is already fully qualified (i.e. begins with the
- *  default schema prefix, this routine will not change it.
- *
- *  @param name A partial schema name.  The default prefix is
- *  prepended to this name to produce a fully qualified schema
- *  name.
- *
- *  @return This function returns a string pointer to the fully
- *  qualified schema name.  It is the caller's responsibility to
- *  free this string.
- */
-gchar *gnc_gsettings_normalize_schema_name (const gchar *name);
-
 /** Get the default gsettings schema prefix.
  *  If none was set explicitly, this defaults to
  *  "org.gnucash.GnuCash"



Summary of changes:
 libgnucash/app-utils/gnc-gsettings.cpp | 98 ++++++++++++++++++++--------------
 libgnucash/app-utils/gnc-gsettings.h   | 18 -------
 2 files changed, 58 insertions(+), 58 deletions(-)



More information about the gnucash-changes mailing list