-
-
Notifications
You must be signed in to change notification settings - Fork 166
Segmentation fault in mlua userdata caused by storing a Lua VM handle in a userdata with generic parameters #552
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
Here's the backtrace btw @khvzak Thread 18 "lua-vm-threadpo" received signal SIGILL, Illegal instruction. |
I did some debugging and the segfault happens due to it trying to destroy the same userdata twice????
|
@khvzak did more testing and tracked down the issue to having a Lua VM handle in a userdata that also has a generic parameter. This causes the UserData to be freed multiple times during lua garbage collection (likely due to a bug in mlua’s Drop(??) implementation) leading to a double free and hence a segmentation fault Wrapping the Lua VM in a ManuallyDrop or removing the mlua::Lua solves the issue making it very likely a bug in mlua::Lua’s Drop implementation conflicting with how userdata is destructed somehow leading to a double free. |
Managed to get a nice minimal reproducible example @khvzak use mlua::prelude::*;
pub struct MyUserData<T: 'static + Clone> {
pub lua: mlua::Lua,
v: T
}
impl<T: 'static + Clone> LuaUserData for MyUserData<T> {}
fn main() {
let lua = mlua::Lua::new();
let my_userdata: MyUserData<String> = MyUserData {
lua: lua.clone(),
v: "Hello".to_string(),
};
let mv = (10, my_userdata).into_lua_multi(&lua).unwrap();
for i in 1..10 {
load(&lua, mv.clone());
}
}
fn load(lua: &mlua::Lua, mv: LuaMultiValue) {
lua.load("return 1")
.call::<()>(mv)
.unwrap();
} Note that the generics above as well as into_lua_multi() are optional, so the below also Illegal Instructions (or segfaults sometimes) as well: use mlua::prelude::*;
#[derive(Clone, Debug)]
pub struct MyUserData {
lua: Lua,
v: String,
}
impl LuaUserData for MyUserData {}
fn main() {
let lua = mlua::Lua::new();
let my_userdata: MyUserData = MyUserData {
lua: lua.clone(),
v: "Hello".to_string(),
};
let mv = (10, my_userdata);
for i in 1..10 {
load(&lua, mv.clone());
}
}
fn load(lua: &mlua::Lua, mv: impl IntoLuaMulti) {
lua.load("return 1")
.call::<()>(mv)
.unwrap();
} This specific example doesn't seem to segfault in release but its still possible to encounter using some slight modifications in release mode as well |
The minimal example would be as simple as: let lua = Lua::new();
lua.create_any_userdata(lua.clone())?; The crash is happens because when
Lua (VM) not designed to handle this case unfortunately. Seems I need to remove enforced garbage collection on Lua drop. |
The problem is more complex than I anticipated. To address this issue, I made few changes:
|
Btw, I added |
Decided to make this a sep issue from the Github Discussion as its pretty big.
The latest mlua build (with luau 667 and thread callbacks) now gives me segmentation faults
The text was updated successfully, but these errors were encountered: