lua-users home
lua-l archive

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


Hi,

first of all sorry for the long email but i could really use some help
here...

i am running lua 5.1 in a C++ environment and i am having a problem with
some user data not being garbage collected and i have been trying to figure
out why for a while without much luck.

the following code is all abstracted but the flow is representative of
production code, some of this may look weird without context but please i am
not looking to any comment on code design, just trying to understand how the
userdata/GC works when you have local references inside coroutines

-----------------------------------------------------------------------
1) i have a "class.lua" module that defines a "New" function for OOP like:

function New(self, obj)
    local obj = obj or {}
    setmetatable(obj, self)
    self.__index = self
    return obj
end

2) i have another module, the one leaking (let's call it "base_module.lua"),
that has the following code

local class = require "class"

MyTable = class:New {
    update = function(self)
        if self.co == nil then
            self.co = coroutine.create(self.coroutine_update, self)
        end

        coroutine.resume(self.co, self)
    end,

    coroutine_update = function(self)
        local myref = cbinding.CreateMyUserData()

        while true do
            do_something(myref)
            coroutine.yield()
        end
    end,
}

3) i have one lua file that contains something like:

local base_module = require "base_module"

local tableref = nil

function enter()
    tableref = base_module.MyTable:New {}
end

function update()
    tableref:update()
end

function exit()
    tableref = nil
end
-----------------------------------------------------------------------

now the last lua file is the one that i am actually running from the C side,
every time i decide to run it i call the enter function then i start calling
update into a loop and when i don't need it anymore i call the exit
function.

When i call the exit function what I would expect is for tableref to be
collected -> "tableref.co" coroutine to be collected since there are no more
references to it -> userdata "myref" inside the coroutine_update to be
collected... which is not happening.

I have then tried to associate the userdata to the object removing the
creation from the coroutine

-----------------------------------------------------------------------
MyTable = class:New {
    New = function (self, obj)
        -- create the userdata at creation time
        local obj = class.New(self, obj)
        obj.myref = cbinding.CreateMyUserData()
        return obj
    end,

    update = function(self)
        if self.co == nil then
            self.co = coroutine.create(self.coroutine_update, self)
        end

        coroutine.resume(self.co, self)
    end,

    coroutine_update = function(self)
        -- reference the userdata associated to the object
        local myref = self.myref

        while true do
            do_something(myref)
            coroutine.yield()
        end
    end,
}
-----------------------------------------------------------------------

This didn't fix the problem.

Then i thought that since functions are first class values in lua maybe the
object "MyTable" in the "base_module.lua" itself could be keeping a
reference through the "coroutine_update" variable so i have moved it outside
the table in the same file hoping to fix it

-----------------------------------------------------------------------
local function coroutine_update(self)
    -- reference the userdata associated to the object
    local myref = self.myref

    while true do
        do_something(myref)
        coroutine.yield()
    end
end

MyTable = class:New {
    New = function (self, obj)
        -- create the userdata at creation time
        local obj = class.New(self, obj)
        obj.myref = cbinding.CreateMyUserData()
        return obj
    end,

    update = function(self)
        if self.co == nil then
            -- removed the self. from coroutine_update
            self.co = coroutine.create(coroutine_update, self)
        end

        coroutine.resume(self.co, self)
    end,

}
-----------------------------------------------------------------------

which of course didn't fix it either.
>From what i understand if the coroutine is freed then all local variables
inside that function should be garbage collected, at that point the userdata
shouldn't have any references anymore and should be collected too but for
some reason this is not happening.

I will keep investigating but any help/suggestions/thoughts will be highly
appreciated.

Thank you



--
View this message in context: http://lua.2524044.n2.nabble.com/coroutines-local-userdata-and-GC-tp7664107.html
Sent from the Lua-l mailing list archive at Nabble.com.