luau-lang / luau

A fast, small, safe, gradually typed embeddable scripting language derived from Lua
https://luau.org
MIT License
4.07k stars 384 forks source link

Access lua_State and userdata in the lua_newuserdatadtor dtor callback #1446

Open kunitoki opened 1 month ago

kunitoki commented 1 month ago

Is it possible to have:

void* lua_newuserdatadtor(lua_State* L, size_t sz, void (*dtor)(void*, lua_State*))

so it's possible to query the lua_State* in the destructor to access any potential metatable of the userdata before it's destructed ?

checkraisefold commented 1 month ago

This is used for most destructors in existing Lua-binding code that modify __gc, so this would be extremely useful to have especially when porting code!

kunitoki commented 1 month ago

It would need to have the userdata still alive and on top of the stack to be useful tho, not sure if this will create some sort of issues (userdata needs to be alive when the method is called, but then the inner object is deleted in there, turning the userdata to a dangling that needs to be dealt with).

For me it will allow to execute custom weak tables unregistrations in the registry when objects die. This feature i'm porting over from puc-lua/luajit cannot be implemented in luau and i have to resort to extremely horrible and inefficient hacks.

bjcscat commented 1 month ago

This would definitely be a welcome addition though I'm not sure how backwards compatibility would be addressed

vegorov-rbx commented 1 month ago

This is a duplicate of https://github.com/luau-lang/luau/pull/510

TLDR: it is generally unsafe with Luau to perform mutating operations on the VM state from inside the userdata destructor call. We tried to omit the argument to reduce the possibility of mistakes like that.

kunitoki commented 1 month ago

It's a bit unfortunate, but i can understand the risks. But maybe someone can decide to take the risk? I would need to create wrapper proxies for all objects and perform an indirection at every access in the case of missing the functionality...

vegorov-rbx commented 1 month ago

One solution that we talked about was to include the global thread userdata pointer. That userdata is often set up to point to all the side data of the VM instance. It can then be used to record any required updates to be made after execution returns from Luau to the host.

I guess some might even place the global lua_State in that userdata and still do questionable things, but at least API will not be guiding towards that.