[issue33909] PyObject_CallFinalizerFromDealloc is not referenced in any documentation
![](https://secure.gravatar.com/avatar/fa0f7819f1825f596b384c19aa7dcf33.jpg?s=120&d=mm&r=g)
New submission from Eric Wieser <wieser.eric+pybug@gmail.com>: PEP 442 states that:
Two new C API functions are provided to ease calling of tp_finalize, especially from custom deallocators.
But it does not give the names of these functions, nor do any python docs I can discover.
From grepping for tp_finalize, it seems the functions in question are:
- PyObject_CallFinalizerFromDealloc - PyObject_CallFinalizer It would be great if these could be documented, and perhaps even an example given of when it's appropriate to call each one. ---------- assignee: docs@python components: Documentation messages: 320036 nosy: Eric.Wieser, docs@python priority: normal severity: normal status: open title: PyObject_CallFinalizerFromDealloc is not referenced in any documentation versions: Python 3.4, Python 3.5, Python 3.6, Python 3.7, Python 3.8 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue33909> _______________________________________
![](https://secure.gravatar.com/avatar/fa0f7819f1825f596b384c19aa7dcf33.jpg?s=120&d=mm&r=g)
INADA Naoki <songofacandy@gmail.com> added the comment: I think I can describe what two function does/for. But I'm not good English writer. Would you write document instead? --- "Finalizer" is __del__ in Python and tp_finalize in C. Calling finalizer requires some tricks, including avoiding call twice. That is what PyObject_CallFinalizer() does. Use it instead of call `type->tp_finalize(obj)` directly. But finalizer is called from destructor (tp_dealloc) usually, and calling finalizer from destructor need more hack (e.g. temporary increment refcount). This is what PyObject_CallFinalizerFromDealloc does. Generally speaking, this API is used only when you want to use both of custom tp_dealloc and tp_finalize. This is very rare because you can write cleanup code in tp_dealloc and skip using tp_finalize. When you need really need both of tp_dealloc and tp_finalize, note that: * Finalizer may resurrect the object. * When the type is subclassed from Python, tp_finalize is called automatically. You must not call PyObject_CallFinalizerFromDealloc then. This is tp_dealloc of Future object in asyncio. This object uses both of tp_dealloc and tp_finalize for compatibility with Future object implemented in pure Python. This covers many edge cases of tp_dealloc. ``` static void FutureObj_dealloc(PyObject *self) { FutureObj *fut = (FutureObj *)self; if (Future_CheckExact(fut)) { /* When fut is subclass of Future, finalizer is called from * subtype_dealloc. */ if (PyObject_CallFinalizerFromDealloc(self) < 0) { // resurrected. return; } } // Weakref callback and finalizer of other objects may start GC. // So you need to untrack this object from GC before calling PyObject_ClearWeakRefs() // or any Py_DECREF()s // Otherwise, GC will cause segfault because refcount of this object is 0. PyObject_GC_UnTrack(self); // Handle weakrefs if (fut->fut_weakreflist != NULL) { PyObject_ClearWeakRefs(self); } // Reuse tp_clear() for clearing all members. (void)FutureObj_clear(fut); // Free this object at last. Py_TYPE(fut)->tp_free(fut); } ``` ---------- nosy: +inada.naoki _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue33909> _______________________________________
participants (2)
-
Eric Wieser
-
INADA Naoki