summaryrefslogtreecommitdiffstats
path: root/src/core/settings.c
diff options
context:
space:
mode:
authorMichael Brown2011-03-23 21:17:24 +0100
committerMichael Brown2011-03-23 21:17:24 +0100
commit071b4000d99f5a8dc765d82ca6a5c5d06f71d67b (patch)
tree56aecda601d2fc7ea346e45b84d4f96ab84d75aa /src/core/settings.c
parent[settings] Refer to online documentation for settings help (diff)
downloadipxe-071b4000d99f5a8dc765d82ca6a5c5d06f71d67b.tar.gz
ipxe-071b4000d99f5a8dc765d82ca6a5c5d06f71d67b.tar.xz
ipxe-071b4000d99f5a8dc765d82ca6a5c5d06f71d67b.zip
[settings] Avoid memory leak when unregistering autovivified settings blocks
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core/settings.c')
-rw-r--r--src/core/settings.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/core/settings.c b/src/core/settings.c
index b9df5a7a..9b924bc8 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -230,6 +230,27 @@ struct generic_settings generic_settings_root = {
/** Root settings block */
#define settings_root generic_settings_root.settings
+/** Autovivified settings block */
+struct autovivified_settings {
+ /** Reference count */
+ struct refcnt refcnt;
+ /** Generic settings block */
+ struct generic_settings generic;
+};
+
+/**
+ * Free autovivified settings block
+ *
+ * @v refcnt Reference count
+ */
+static void autovivified_settings_free ( struct refcnt *refcnt ) {
+ struct autovivified_settings *autovivified =
+ container_of ( refcnt, struct autovivified_settings, refcnt );
+
+ generic_settings_clear ( &autovivified->generic.settings );
+ free ( autovivified );
+}
+
/**
* Find child named settings block
*
@@ -264,7 +285,7 @@ static struct settings * find_child_settings ( struct settings *parent,
static struct settings * autovivify_child_settings ( struct settings *parent,
const char *name ) {
struct {
- struct generic_settings generic;
+ struct autovivified_settings autovivified;
char name[ strlen ( name ) + 1 /* NUL */ ];
} *new_child;
struct settings *settings;
@@ -281,8 +302,11 @@ static struct settings * autovivify_child_settings ( struct settings *parent,
return NULL;
}
memcpy ( new_child->name, name, sizeof ( new_child->name ) );
- generic_settings_init ( &new_child->generic, NULL );
- settings = &new_child->generic.settings;
+ ref_init ( &new_child->autovivified.refcnt,
+ autovivified_settings_free );
+ generic_settings_init ( &new_child->autovivified.generic,
+ &new_child->autovivified.refcnt );
+ settings = &new_child->autovivified.generic.settings;
register_settings ( settings, parent, new_child->name );
return settings;
}