You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
PyObject_CallFinalizerFromDealloc is not referenced in any documentation #78090
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=Noneclosed_at=Nonecreated_at=<Date2018-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=<Date2021-12-03.23:10:41.788>user='https://github.com/eric-wieser'
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);
}
Activity
eric-wieser commentedon Jun 20, 2018
PEP-442 states that:
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:
It would be great if these could be documented, and perhaps even an example given of when it's appropriate to call each one.
methane commentedon 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:
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.
rhansen commentedon Oct 22, 2024
Duplicate of #75459