From 378f73721f960422a4439e0b68f24c645d5a137e Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Sat, 31 Jan 2026 07:14:07 +0900 Subject: [PATCH] slot_del --- crates/vm/src/object/core.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/vm/src/object/core.rs b/crates/vm/src/object/core.rs index 43b2f7dc61a..173b47a757a 100644 --- a/crates/vm/src/object/core.rs +++ b/crates/vm/src/object/core.rs @@ -220,6 +220,11 @@ impl WeakRefList { })) }); let mut inner = unsafe { inner_ptr.as_ref().lock() }; + // If obj was cleared but object is still alive (e.g., new weakref + // created during __del__), restore the obj pointer + if inner.obj.is_none() { + inner.obj = Some(NonNull::from(obj)); + } if is_generic && let Some(generic_weakref) = inner.generic_weakref { let generic_weakref = unsafe { generic_weakref.as_ref() }; if generic_weakref.0.ref_count.get() != 0 { @@ -835,15 +840,34 @@ impl PyObject { slot_del: fn(&PyObject, &VirtualMachine) -> PyResult<()>, ) -> Result<(), ()> { let ret = crate::vm::thread::with_vm(zelf, |vm| { + // Increment twice (0→2) so we can decrement twice below. + zelf.0.ref_count.inc(); zelf.0.ref_count.inc(); + let after_inc = zelf.strong_count(); // Should be 2 + if let Err(e) = slot_del(zelf, vm) { let del_method = zelf.get_class_attr(identifier!(vm, __del__)).unwrap(); vm.run_unraisable(e, None, del_method); } + + let after_del = zelf.strong_count(); + + // First decrement + zelf.0.ref_count.dec(); + + // Check for resurrection: if ref_count increased beyond our expected 2, + // then __del__ created new references (resurrection occurred). + if after_del > after_inc { + // Resurrected - don't do second decrement, leave object alive + return false; + } + + // No resurrection - do second decrement to get back to 0 + // This matches the double increment from inc() zelf.0.ref_count.dec() }); match ret { - // the decref right above set ref_count back to 0 + // the decref set ref_count back to 0 Some(true) => Ok(()), // we've been resurrected by __del__ Some(false) => Err(()),