Skip to content

PyObject_CallFinalizerFromDealloc is not referenced in any documentation #78090

Closed as duplicate

Description

@eric-wieser
BPO 33909
Nosy @pitrou, @methane, @eric-wieser

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2018-06-20.08:23:24.281>
labels = ['3.11', '3.9', '3.10', 'docs']
title = 'PyObject_CallFinalizerFromDealloc is not referenced in any documentation'
updated_at = <Date 2021-12-03.23:10:41.788>
user = 'https://github.com/eric-wieser'

bugs.python.org fields:

activity = <Date 2021-12-03.23:10:41.788>
actor = 'iritkatriel'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation']
creation = <Date 2018-06-20.08:23:24.281>
creator = 'Eric.Wieser'
dependencies = []
files = []
hgrepos = []
issue_num = 33909
keywords = []
message_count = 2.0
messages = ['320036', '320134']
nosy_count = 4.0
nosy_names = ['pitrou', 'methane', 'docs@python', 'Eric.Wieser']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue33909'
versions = ['Python 3.9', 'Python 3.10', 'Python 3.11']

Activity

  1. eric-wieser commented on Jun 20, 2018

    eric-wiesermannequin
    MannequinAuthor

    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.

  2. methane commented on Jun 21, 2018

    @methane
    Member

    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);
    }
    
  3. added
    3.11only security fixes
    and removed on Dec 3, 2021
  4. transferred this issue fromon Apr 10, 2022
  5. rhansen commented on Oct 22, 2024

    @rhansen
    Contributor

    Duplicate of #75459

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.10 (EOL)end of life3.11only security fixes3.9 (EOL)end of lifedocsDocumentation in the Doc dir

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions