sol2 icon indicating copy to clipboard operation
sol2 copied to clipboard

usertype garbage_collect method not getting called

Open JRFarmer opened this issue 6 months ago • 2 comments

I'm trying to wrap a C interface with sol::usertype. For example, the zlib file-based API has a gzopen method that returns a gzFile and you close it (and free the memory) by calling gzclose. So I setup the open method as a sol::factory and the close method as the garbage_collect meta method. I am seeing the close method is never getting called.

Is it a bug or am I doing this wrong?

I'm using Lua 5.3 and sol 2.20.6 (my compiler does not support C++17).

Here's a nonsense example I worked-up on godbolt to demonstrate the problem. Obviously godbolt only has sol 3, but the same problem reproduces there, too. https://godbolt.org/z/f13Kbbn7n

This is the source:

#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>

struct Foo
{
    int bar;
};

Foo* foo_open()
{
    auto* foo = new Foo();
    std::cout << __func__ << " " << foo << std::endl;
    return foo;
}

void foo_close(Foo* foo)
{
    std::cout << __func__ << " " << foo << std::endl;
    delete foo;
}

int main() {
    sol::state lua;
    lua.open_libraries();
    
    lua.new_usertype<Foo>("Foo",
        "new", sol::factories(&foo_open),
        sol::meta_function::garbage_collect, sol::destructor(&foo_close)
    );

    lua.script("f = Foo.new()");

    return 0;
}

This is the output:

ASM generation compiler returned: 0
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/crt1.o: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/libm.so.6: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/libmvec.so.1: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
/opt/compiler-explorer/gcc-8.4.0/bin/../lib/gcc/x86_64-linux-gnu/8.4.0/../../../../x86_64-linux-gnu/bin/ld: warning: /lib/x86_64-linux-gnu/libc.so.6: unsupported GNU_PROPERTY_TYPE (5) type: 0xc0008002
Execution build compiler returned: 0
Program returned: 0
foo_open 0x2f677860

Notice the foo_close method is not called.

JRFarmer avatar Jul 06 '25 12:07 JRFarmer

From usertype memory:

sol does not take ownership of raw pointers, returned from functions or set through the set functions. Return a value, a std::unique_ptr, a std::shared_ptr of some kind...

If you change the return value to a unique pointer, you can see the destructor being called: https://godbolt.org/z/669fGrEr4.

I think it's easiest if you return a std::unique_ptr with a custom deleter - something like std::unique_ptr<gzFile, gzglose>.

Nerixyz avatar Jul 06 '25 13:07 Nerixyz

sol does not take ownership of raw pointers

I don't want sol to take ownership. I do want sol to call the garbage_collect method if one is provided. The garbage_collect method is never called and that's the part I think is a bug.

If you change the return value to a unique pointer... ...return a std::unique_ptr with a custom deleter...

This is what I was expecting to do as a work-around. I need to pre-wrap the C-library API before using it in the usertype definition. That's unfortunate.

JRFarmer avatar Jul 06 '25 13:07 JRFarmer