(
zelf: &PyObject,
slot_del: fn(&PyObject, &VirtualMachine) -> PyResult<()>,
)
| 1599 | #[inline(never)] |
| 1600 | #[cold] |
| 1601 | fn call_slot_del( |
| 1602 | zelf: &PyObject, |
| 1603 | slot_del: fn(&PyObject, &VirtualMachine) -> PyResult<()>, |
| 1604 | ) -> Result<(), ()> { |
| 1605 | let ret = crate::vm::thread::with_vm(zelf, |vm| { |
| 1606 | // Temporarily resurrect (0→2) so ref_count stays positive |
| 1607 | // during __del__, preventing safe_inc from seeing 0. |
| 1608 | zelf.0.ref_count.inc_by(2); |
| 1609 | |
| 1610 | if let Err(e) = slot_del(zelf, vm) { |
| 1611 | let del_method = zelf.get_class_attr(identifier!(vm, __del__)).unwrap(); |
| 1612 | vm.run_unraisable(e, None, del_method); |
| 1613 | } |
| 1614 | |
| 1615 | // Undo the temporary resurrection. Always remove both |
| 1616 | // temporary refs; the second dec returns true only when |
| 1617 | // ref_count drops to 0 (no resurrection). |
| 1618 | let _ = zelf.0.ref_count.dec(); |
| 1619 | zelf.0.ref_count.dec() |
| 1620 | }); |
| 1621 | match ret { |
| 1622 | // the decref set ref_count back to 0 |
| 1623 | Some(true) => Ok(()), |
| 1624 | // we've been resurrected by __del__ |
| 1625 | Some(false) => Err(()), |
| 1626 | None => Ok(()), |
| 1627 | } |
| 1628 | } |
| 1629 | |
| 1630 | // __del__ should only be called once (like _PyGC_FINALIZED check in GIL_DISABLED) |
| 1631 | // We call __del__ BEFORE clearing weakrefs to allow the finalizer to access |
nothing calls this directly
no test coverage detected