[docs] [issue33909] PyObject_CallFinalizerFromDealloc is not referenced in any documentation

INADA Naoki report at bugs.python.org
Wed Jun 20 22:33:23 EDT 2018

INADA Naoki <songofacandy at 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.

    // 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.

    // Handle weakrefs
    if (fut->fut_weakreflist != NULL) {

    // Reuse tp_clear() for clearing all members.

    // Free this object at last.

nosy: +inada.naoki

Python tracker <report at bugs.python.org>

More information about the docs mailing list