@@ -220,6 +220,11 @@ impl WeakRefList {
220220 } ) )
221221 } ) ;
222222 let mut inner = unsafe { inner_ptr. as_ref ( ) . lock ( ) } ;
223+ // If obj was cleared but object is still alive (e.g., new weakref
224+ // created during __del__), restore the obj pointer
225+ if inner. obj . is_none ( ) {
226+ inner. obj = Some ( NonNull :: from ( obj) ) ;
227+ }
223228 if is_generic && let Some ( generic_weakref) = inner. generic_weakref {
224229 let generic_weakref = unsafe { generic_weakref. as_ref ( ) } ;
225230 if generic_weakref. 0 . ref_count . get ( ) != 0 {
@@ -835,15 +840,34 @@ impl PyObject {
835840 slot_del : fn ( & PyObject , & VirtualMachine ) -> PyResult < ( ) > ,
836841 ) -> Result < ( ) , ( ) > {
837842 let ret = crate :: vm:: thread:: with_vm ( zelf, |vm| {
843+ // Note: inc() from 0 does a double increment (0→2) for thread safety.
844+ // This gives us "permission" to decrement twice.
838845 zelf. 0 . ref_count . inc ( ) ;
846+ let after_inc = zelf. strong_count ( ) ; // Should be 2
847+
839848 if let Err ( e) = slot_del ( zelf, vm) {
840849 let del_method = zelf. get_class_attr ( identifier ! ( vm, __del__) ) . unwrap ( ) ;
841850 vm. run_unraisable ( e, None , del_method) ;
842851 }
852+
853+ let after_del = zelf. strong_count ( ) ;
854+
855+ // First decrement
856+ zelf. 0 . ref_count . dec ( ) ;
857+
858+ // Check for resurrection: if ref_count increased beyond our expected 2,
859+ // then __del__ created new references (resurrection occurred).
860+ if after_del > after_inc {
861+ // Resurrected - don't do second decrement, leave object alive
862+ return false ;
863+ }
864+
865+ // No resurrection - do second decrement to get back to 0
866+ // This matches the double increment from inc()
843867 zelf. 0 . ref_count . dec ( )
844868 } ) ;
845869 match ret {
846- // the decref right above set ref_count back to 0
870+ // the decref set ref_count back to 0
847871 Some ( true ) => Ok ( ( ) ) ,
848872 // we've been resurrected by __del__
849873 Some ( false ) => Err ( ( ) ) ,
0 commit comments