lupa
lupa copied to clipboard
Memory leak
A dependency cycle avoids both Lua references and Python references from being collected by their respective garbage collection systems.
How to reproduce
This example uses __gc on tables, which is a feature not present in Lua 5.1, but is only there to show how the Lua object is not collected.
from lupa import LuaRuntime
lua = LuaRuntime()
lua_f = lua.eval('function(t) setmetatable(t, {__gc = print}) end')
###########################
# Normal behaviour
t = lua.table()
lua_f(t)
t = None
lua.execute('collectgarbage()')
# prints "table: <address>"
###########################
############################
# Unexpected behaviour
t = lua.table()
lua_f(t)
d = { "table": t }
t["dict"] = d
d = None
t = None
lua.execute('collectgarbage()')
# prints nothing --> table is not collected
#############################
Is this impacted by the refcouting changes in #171?
Is this impacted by the refcouting changes in #171?
No, there is still a reference cycle.
Basically, in the example I gave, d
is holding "hostage" the reference to _LuaTable
, which holds "hostage" the reference to the Lua table in the registry (altough Python can't track the reference identifier down). In Lua, the table is holding "hostage" the reference to the userdata that points to d
.
dict ---> _LuaTable (Python)
^ |
| V
userdata <--- table (Lua)
I am using the word "hostage" here figuratively to emphasize that it's the only reference left! The problem here is that while there is clearly for us a reference cycle, it is split between languages and they can't see the full picture.