Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

record: avoid memory leaks for embedded recs needing uninit

The main offender was GObject.Value, which needs g_value_unset() to be
called even when we provided the space for GValue to live (i.e. iot
was embedded kind of Record).
  • Loading branch information...
commit 2ffbc77129f67b357d8da460579730c87cbfcd11 1 parent c5065d1
@pavouk authored
Showing with 27 additions and 11 deletions.
  1. +1 −1  lgi/gi.c
  2. +4 −0 lgi/override/GObject-Value.lua
  3. +22 −10 lgi/record.c
View
2  lgi/gi.c
@@ -53,7 +53,7 @@ lgi_gi_load_function (lua_State *L, int typetable, const char *name)
g_typelib_symbol (g_base_info_get_typelib (*info),
g_function_info_get_symbol (*info), &symbol);
else if (lua_islightuserdata (L, -1))
- symbol = lua_touserdata (L, -1);
+ symbol = lua_touserdata (L, -1);
lua_pop (L, 1);
return symbol;
}
View
4 lgi/override/GObject-Value.lua
@@ -39,6 +39,10 @@ end
local value_field_gtype = Value._field.g_type
Value._field = nil
+-- Register _uninit function, to avoid memory leaks from values which
+-- are inline-allocated by core.record.new.
+Value._uninit = gi.GObject.resolve.g_value_unset
+
-- 'type' property controls gtype of the property.
Value._attribute = { gtype = {} }
function Value._attribute.gtype.get(value)
View
32 lgi/record.c
@@ -324,7 +324,18 @@ static int
record_gc (lua_State *L)
{
Record *record = record_get (L, 1);
- if (record->store == RECORD_STORE_ALLOCATED)
+
+ if (record->store == RECORD_STORE_EMBEDDED
+ || record->store == RECORD_STORE_NESTED)
+ {
+ /* Check whether record has registered '_uninit' function, and
+ invoke it if yes. */
+ lua_getfenv (L, 1);
+ void (*uninit)(gpointer) = lgi_gi_load_function (L, -1, "_uninit");
+ if (uninit != NULL)
+ uninit (record->addr);
+ }
+ else if (record->store == RECORD_STORE_ALLOCATED)
{
/* Free the owned record. */
GType gtype;
@@ -365,7 +376,8 @@ record_gc (lua_State *L)
}
}
}
- else if (record->store == RECORD_STORE_NESTED)
+
+ if (record->store == RECORD_STORE_NESTED)
{
/* Free the reference to the parent. */
lua_pushlightuserdata (L, record);
@@ -603,15 +615,15 @@ record_set (lua_State *L)
{
/* Change ownership type of the record. */
if (lua_toboolean (L, 2))
- {
- if (record->store == RECORD_STORE_EXTERNAL)
- record->store = RECORD_STORE_ALLOCATED;
- }
+ {
+ if (record->store == RECORD_STORE_EXTERNAL)
+ record->store = RECORD_STORE_ALLOCATED;
+ }
else
- {
- if (record->store == RECORD_STORE_ALLOCATED)
- record->store = RECORD_STORE_EXTERNAL;
- }
+ {
+ if (record->store == RECORD_STORE_ALLOCATED)
+ record->store = RECORD_STORE_EXTERNAL;
+ }
}
return 0;
Please sign in to comment.
Something went wrong with that request. Please try again.