Simplify handling of userdata __gc and resurrected userdata.

Now, simply remove the userdata table immediately before dropping the userdata.
This does two things, it prevents __gc from double dropping the userdata, and
after the first call to __gc, it prevents the userdata from being identified as
any particular userdata type, so it cannot be misused after being finalized.

This change thus removes the userdata invalidation error, and simplifies a lot
of userdata handling code.

It also fixes a panic bug.  Because there is no predictable order for
finalizers, it is possible to run a userdata finalizer that does not resurrect
itself before a lua table finalizer that accesses that userdata, and this means
that there were several asserts that were possible to trigger in normal Lua code
in util.rs related to `WrappedError`.

Now, finalized userdata is simply a userdata with no methods, so any use of
finalized userdata becomes a normal script runtime error (though, with a
potentially confusing error message).  As a future improvement, we could set
a metatable on finalized userdata that provides a better error message.
This commit is contained in:
kyren
2018-01-27 18:12:39 -05:00
parent cbc882bad0
commit 77eb73a50c
4 changed files with 50 additions and 52 deletions
+1 -1
View File
@@ -957,7 +957,7 @@ impl Lua {
ephemeral: true,
};
let func = get_userdata::<RefCell<Callback>>(state, ffi::lua_upvalueindex(1))?;
let func = get_userdata::<RefCell<Callback>>(state, ffi::lua_upvalueindex(1));
let mut func = (*func)
.try_borrow_mut()
.map_err(|_| Error::RecursiveCallbackError)?;