1. Anders Ruud
  2. love
  3. Issues

Issues

Issue #1267 resolved

Memory leak when using threads

Henrique Gemignani
created an issue

The attached code has a memory leak: the love::graphics::opengl::Image object keeps a positive object count even after the lua state is closed.

This can be confirmed easily by watching the love::graphics::Volatile::all container.

The bug occurs on 0.10.2, and the tip of default and minor.

Comments (9)

  1. Alex Szpakowski

    This only occurs if the module that the object belongs to isn't require'd in the thread's code by the time the thread GC's it (most modules are not loaded by default in threads – and also love.graphics objects and functions are not allowed in threads anyway).

  2. Henrique Gemignani reporter

    Nice, that's exactly the case in my original code. An Image object is sent to a thread, only to be sent back to the main thread. Since it's not used, and it's not safe to be used, the love.graphics module wasn't loaded.

    That's an interesting restriction. It would good for it be at least documented. Ideally, trying to get the userdata of a not-loaded module should throw an error.

    Looking for the code, it seems to be because the metatable of created proxy does not exist, leading to no __gc being called. Is this correct?

  3. Alex Szpakowski

    It's a bug that it's not cleaned up correctly in this case, I was just pointing out that the bug only happens in limited circumstances where it should probably error anyway. :)

    Looking for the code, it seems to be because the metatable of created proxy does not exist, leading to no __gc being called. Is this correct?

    Yep - the object has a metatable but it's empty because the module hasn't been loaded and the module is what populates the metatable.

  4. Henrique Gemignani reporter

    Ok!

    Also, clearly unrelated to the main issue now, but I found this on my investigation:

    Variant &Variant::operator = (const Variant &v)
    {
    ....
        if (type == STRING)
            data.string->release();
        else if (type == FUSERDATA && v.data.userdata != nullptr)
            ((love::Object *) v.data.userdata)->release();
        else if (type == TABLE)
            data.table->release();
    

    It seems the data.userdata->release() is being called on the argument instead of the field here.

  5. Alex Szpakowski

    I don't plan to release another 0.10.x version of LÖVE. If you're having memory leaks because of this bug in 0.10.2, can't you just not push objects to the thread that are not part of a module loaded by the thread?

  6. Henrique Gemignani reporter

    Oh, no worries, I can just backport the fix myself.

    Also, thanks for the info on 0.10.x releases, I was planning some pull requests soon, I'll make sure they're based on minor then.

  7. Log in to comment