A GC debugging question

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

A GC debugging question

Dibyendu Majumdar
Hi,

I am trying to debug the following test in Ravi - this is failing
after porting the Lua 5.4 GC to Ravi. Note that Ravi still uses the
old style ref-counted upvalues from Lua 5.3. This test used to pass
before the port, and also passes in Lua 5.4 (it is part of the test
suite) so the problem is somewhere in the ported version.

collectgarbage("incremental")
-- Create a closure (function inside 'f') with an upvalue ('param') that
-- points (through a table) to the closure itself and to the thread
-- ('co' and the initial value of 'param') where closure is running.
-- Then, assert that table (and therefore everything else) will be
-- collected.
do
  local collected = false   -- to detect collection
  collectgarbage(); collectgarbage("stop")
  do
    local function f (param)
      ;(function ()
        assert(type(f) == 'function' and type(param) == 'thread')
        param = {param, f}
        setmetatable(param, {__gc = function () collected = true end})
        coroutine.yield(100)
      end)()
    end
    local co = coroutine.create(f)
    assert(coroutine.resume(co, co))
  end
  -- Now, thread and closure are not reacheable any more.
  collectgarbage()
  -- FIXME
  assert(collected)
  collectgarbage("restart")
end


The final assertion fails.
If I insert another collection before the assertion then it is successful.
Fyi I am running with LTESTS enabled, and I have tried inserting
T.checkmemory() as well - no issues reported.

My question is this: what's the best way to debug this?
I find that there are so many steps that it is kind of hard to figure
out how to pinpoint the issue. It seems that the problem might be that
the coroutine thread is not collected when it should be?

I should perhaps add a debugging facility to dump out all objects that
are live prior to the collection.

Sorry this is a vague question, I know some of you are very good at
this sort of debugging, so any pointers would be appreciated.

Regards
Dibyendu
Reply | Threaded
Open this post in threaded view
|

Re: A GC debugging question

Dibyendu Majumdar
Looks like I was mistaken about Lua 5.3 - as the test in 5.3 is different.

  -- Now, thread and closure are not reacheable any more;
  -- two collections are needed to break cycle
  collectgarbage()
  assert(not collected)
  collectgarbage()
  assert(collected)

so it works as expected!


On Fri, 25 Dec 2020 at 00:52, Dibyendu Majumdar <[hidden email]> wrote:

>
> Hi,
>
> I am trying to debug the following test in Ravi - this is failing
> after porting the Lua 5.4 GC to Ravi. Note that Ravi still uses the
> old style ref-counted upvalues from Lua 5.3. This test used to pass
> before the port, and also passes in Lua 5.4 (it is part of the test
> suite) so the problem is somewhere in the ported version.
>
> collectgarbage("incremental")
> -- Create a closure (function inside 'f') with an upvalue ('param') that
> -- points (through a table) to the closure itself and to the thread
> -- ('co' and the initial value of 'param') where closure is running.
> -- Then, assert that table (and therefore everything else) will be
> -- collected.
> do
>   local collected = false   -- to detect collection
>   collectgarbage(); collectgarbage("stop")
>   do
>     local function f (param)
>       ;(function ()
>         assert(type(f) == 'function' and type(param) == 'thread')
>         param = {param, f}
>         setmetatable(param, {__gc = function () collected = true end})
>         coroutine.yield(100)
>       end)()
>     end
>     local co = coroutine.create(f)
>     assert(coroutine.resume(co, co))
>   end
>   -- Now, thread and closure are not reacheable any more.
>   collectgarbage()
>   -- FIXME
>   assert(collected)
>   collectgarbage("restart")
> end
>
>
> The final assertion fails.
> If I insert another collection before the assertion then it is successful.
> Fyi I am running with LTESTS enabled, and I have tried inserting
> T.checkmemory() as well - no issues reported.
>
> My question is this: what's the best way to debug this?
> I find that there are so many steps that it is kind of hard to figure
> out how to pinpoint the issue. It seems that the problem might be that
> the coroutine thread is not collected when it should be?
>
> I should perhaps add a debugging facility to dump out all objects that
> are live prior to the collection.
>
> Sorry this is a vague question, I know some of you are very good at
> this sort of debugging, so any pointers would be appreciated.
>
> Regards
> Dibyendu