Skip to content

Commit 5fd96c7

Browse files
committed
Don't run GC finalizers on ref thread.
If this happen then we don't have full access to the ref thread stack. Fixes #491
1 parent 7a3f19b commit 5fd96c7

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

src/state.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,8 +1043,8 @@ impl Lua {
10431043
let state = lua.state();
10441044
unsafe {
10451045
if lua.unlikely_memory_error() {
1046-
crate::util::push_buffer(lua.ref_thread(), buf.as_ref(), false)?;
1047-
return Ok(Buffer(lua.pop_ref_thread()));
1046+
crate::util::push_buffer(state, buf.as_ref(), false)?;
1047+
return Ok(Buffer(lua.pop_ref()));
10481048
}
10491049

10501050
let _sg = StackGuard::new(state);

src/state/raw.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,8 @@ impl RawLua {
432432
pub(crate) unsafe fn create_string(&self, s: impl AsRef<[u8]>) -> Result<String> {
433433
let state = self.state();
434434
if self.unlikely_memory_error() {
435-
push_string(self.ref_thread(), s.as_ref(), false)?;
436-
return Ok(String(self.pop_ref_thread()));
435+
push_string(state, s.as_ref(), false)?;
436+
return Ok(String(self.pop_ref()));
437437
}
438438

439439
let _sg = StackGuard::new(state);
@@ -444,12 +444,12 @@ impl RawLua {
444444

445445
/// See [`Lua::create_table_with_capacity`]
446446
pub(crate) unsafe fn create_table_with_capacity(&self, narr: usize, nrec: usize) -> Result<Table> {
447+
let state = self.state();
447448
if self.unlikely_memory_error() {
448-
push_table(self.ref_thread(), narr, nrec, false)?;
449-
return Ok(Table(self.pop_ref_thread()));
449+
push_table(state, narr, nrec, false)?;
450+
return Ok(Table(self.pop_ref()));
450451
}
451452

452-
let state = self.state();
453453
let _sg = StackGuard::new(state);
454454
check_stack(state, 3)?;
455455
push_table(state, narr, nrec, true)?;
@@ -734,6 +734,10 @@ impl RawLua {
734734

735735
pub(crate) unsafe fn drop_ref(&self, vref: &ValueRef) {
736736
let ref_thread = self.ref_thread();
737+
mlua_debug_assert!(
738+
ffi::lua_gettop(ref_thread) >= vref.index,
739+
"GC finalizer is not allowed in ref_thread"
740+
);
737741
ffi::lua_pushnil(ref_thread);
738742
ffi::lua_replace(ref_thread, vref.index);
739743
(*self.extra.get()).ref_free.push(vref.index);

tests/tests.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,3 +1377,21 @@ fn test_exec_raw() -> Result<()> {
13771377

13781378
Ok(())
13791379
}
1380+
1381+
#[test]
1382+
fn test_gc_drop_ref_thread() -> Result<()> {
1383+
let lua = Lua::new();
1384+
1385+
let t = lua.create_table()?;
1386+
lua.create_function(move |_, ()| {
1387+
_ = &t;
1388+
Ok(())
1389+
})?;
1390+
1391+
for _ in 0..10000 {
1392+
// GC will run eventually to collect the function and the table above
1393+
lua.create_table()?;
1394+
}
1395+
1396+
Ok(())
1397+
}

0 commit comments

Comments
 (0)