Skip to content

PyObject_CallFinalizerFromDealloc is not referenced in any documentation #78090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
eric-wieser mannequin opened this issue Jun 20, 2018 · 3 comments
Open

PyObject_CallFinalizerFromDealloc is not referenced in any documentation #78090

eric-wieser mannequin opened this issue Jun 20, 2018 · 3 comments
Labels
3.9 only security fixes 3.10 only security fixes 3.11 only security fixes docs Documentation in the Doc dir

Comments

@eric-wieser
Copy link
Mannequin

eric-wieser mannequin commented Jun 20, 2018

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']

@eric-wieser
Copy link
Mannequin Author

eric-wieser mannequin commented Jun 20, 2018

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.

@eric-wieser eric-wieser mannequin added 3.7 (EOL) end of life 3.8 (EOL) end of life labels Jun 20, 2018
@eric-wieser eric-wieser mannequin assigned docspython Jun 20, 2018
@eric-wieser eric-wieser mannequin added the docs Documentation in the Doc dir label Jun 20, 2018
@methane
Copy link
Member

methane commented Jun 21, 2018

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);
}

@iritkatriel iritkatriel added 3.9 only security fixes 3.10 only security fixes 3.11 only security fixes and removed 3.7 (EOL) end of life 3.8 (EOL) end of life labels Dec 3, 2021
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@rhansen
Copy link
Contributor

rhansen commented Oct 22, 2024

Duplicate of #75459

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.9 only security fixes 3.10 only security fixes 3.11 only security fixes docs Documentation in the Doc dir
Projects
None yet
Development

No branches or pull requests

3 participants