-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Allow to disable drop from running during unwind #3807
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Can you mark the messages |
Thanks for the idea. I don't think that is possible. I just updated my above comment to add more context. Please let me know if you don't understand which part since English is my second language and it quite hard for me to explain complex things. |
Can you elaborate why using |
I know the purpose of |
how about using |
That is one possible solution but it is also introduce an overhead. I prefer my current workaround that patch Lua to put the error out of Lua stack before raising an error than this one. |
If the error is fatal enough that you start unwinding the Rust stack, then it makes sense to assume the lua stack is also going away. So I think your solution does seem reasonable; in the lua exception handler you should copy the error to something allocated and then get that pointer to Rust for printing (something global could work, like Regarding the original proposal, I think language support is pretty unlikely since there are plenty of workarounds. If you wanted the behavior as-written, you could route |
It's difficult to tell without more code, but I think this approach is inherently unsound. (See Leakpocolypse)
This is incorrect. There are a variety of ways in which the child item can go out of scope (ie. its lifetime end and the borrow returned) without its destructor being called. To do this safely, you'd need to use the callback pattern, ie. stack.with(item, |stack| {
// Item is pushed onto the stack for the duration of this closure.
});
// Implementation
impl Stack {
pub fn with<R>(&mut self, item: impl LuaValue, f: impl FnOnce(&mut Self) -> R) -> R {
lua_push(item.into());
let result = f(self);
lua_pop();
result
}
} With this pattern, popping will also automatically be skipped if there's a panic. If you don't want that you could use a local variable with a destructor to automate the popping (this is sound because the lifetime of the local is under your control). A further problem is that I'm pretty sure allowing an exception thrown by C++ to cross the FFI boundary is UB. |
#2945 ( |
Ah yes, although that doesn't help in this case because @ultimaweapon can't guarantee that users of their crate don't use |
Thanks for pointing out. Although I occasionally use |
After trying to figure out a solution for this I'm not sure if it is feasible. As @tgross35 stated on the above that it is unlikely for this to happens so I'll close this as the main problem right now is not disable drop from running but how to build a safe API over Lua API. I may end up forking Lua using C2Rust to achieve what I want. Thanks for everyone. |
Background
I'm building a Lua binding that using drop to pop the values from Lua stack. I'll start by explaining how to use Lua API to embed it in the application so people who are not familiar with it can understand the problem I faced. You can proceed to next section if you already know about this.
Lua itself is written in C and it provides C API to embed it. The API is stack-based. You pass the value to Lua by pushing it to Lua stack (not stack on the OS thread) and receive the value from Lua by get it from Lua stack. The following is an example to call a Lua function that return a string with
foo
as the first argument and 5 as the second argument:If the function does not return a string
luaL_checkstring
will push an error message then do a long jump to Lua error handler using Clongjmp
or usingthrow
if it was compiled as C++, which Lua error handler expect this error message on the top of the stack.How my binding works
My binding requires Lua to compile as C++ so
Drop
implementation on Rust type can free any resources automatically when Lua trigger an error. I also represent each of the item in Lua stack as a Rust type that hasDrop
implementation:P
is the parent item in the stack so whendrop
is running it is guarantee that top of the stack always in the same shape as when the value is constructed. This mechanism works really well since it is effectively zero cost. The only problem is it does not works when Lua trigger any error since top of the stack is the error message instead of the last constructed value. I can usestd::uncaught_exceptions()
to check insideDrop
implementation but it is not an optimal solution. Currently I patched Lua source to put the error message somewhere else before it raising a C++ exception so top of the stack has the same shape when drop is running. It would be better if I can excludeDrop
implementation on the above type from running during unwind.The text was updated successfully, but these errors were encountered: