Garbage collected audio sources still accessable via weak tables

Issue #1087 wontfix
Daniel Langner created an issue

I came across this while implementing pause functionality into a game. I store looping audio sources in a weak table in order to pause or resume those sounds when the user hits the pause button. Some audio sources had already been garbage collected, yet while looping over the weak table I could access those (invalid) objects, causing segmentation faults.

To be sure I printed the address of the source in its destructor as well as its pause method. and they matched.

Comments (6)

  1. Daniel Langner reporter

    Sorry, I didn't fully understand how weak tables work. Calling collectgarbage() twice before looping through the weak table resolves the issue.

  2. Bart van Strien

    It still shouldn't happen, it's probably a sign our accounting is off somewhere, that'll be a fun one to track down.

  3. Alex Szpakowski

    I haven't been able to reproduce this with some basic test code (using LÖVE 0.10.0). Can you post some code that reproduces the crash for you?

  4. Daniel Langner reporter
    local sources = setmetatable({}, { __mode = "k" })
    function loadSource(name)
        local s =
        sources[s] = name
        return s
    local engine = loadSource("engine.wav")
    -- force garbage collection
    engine = nil
    function toggle()
        -- this fixes it
    --  collectgarbage()
    --  collectgarbage()
        for s, name in pairs(sources) do
            if s:isPlaying() then
                print("pause ".. name)
                print("resume ".. name)
    function love.keypressed(k)
        if k == "x" then toggle() end
  5. Alex Szpakowski

    Interesting... this appears to be a more fundamental problem with Lua/LuaJIT's implementation of weak keys (it doesn't break for me if I use weak values and set the source as a value rather than a key).

    The issue happens in Lua 5.1, LuaJIT 2.0.3, and LuaJIT 2.1-beta1 for me. It also happens (modify-after-free crash) if I modify the code to use some memory allocated with ffi.C.malloc and automatically garbage collected and deallocated using ffi.gc and, rather than using a LÖVE object. So LÖVE's own code doesn't appear to be causing it.

  6. Log in to comment