Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Throw away the leaking subclasses.
  • Loading branch information
ericsnowcurrently committed Jul 22, 2022
commit 34c5d3b2e8b2a4aaf1264356e092b21ad04f08c7
46 changes: 32 additions & 14 deletions Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -4211,30 +4211,48 @@ type_dealloc_common(PyTypeObject *type)
}


void
_PyStaticType_Dealloc(PyTypeObject *type)
static void
clear_static_tp_subclasses(PyTypeObject *type)
{
/* At this point in the runtime lifecycle, if a type still has
subtypes then some extension module did not correctly finalize
its objects. We can ignore such sybtypes since such extension
modules are already unsafe if the runtime is re-used after
finalization (or in multiple interpreters).

Unfortunately, this means we will leak the objects for which
the subtype owns a reference (directly or indirectly). */
// XXX For now we abandon finalizing the static type here and
// instead leak the type's objects.
if (type->tp_subclasses != NULL) {
if (type->tp_subclasses == NULL) {
return;
}

/* Normally it would be a problem to finalize the type if its
tp_subclasses wasn't cleared first. However, this is only
ever called at the end of runtime finalization, so we can be
more liberal in cleaning up. If the given type still has
subtypes at this point then some extension module did not
correctly finalize its objects.

We can safely obliterate such sybtypes since the extension
Comment thread
ericsnowcurrently marked this conversation as resolved.
Outdated
module and its objects won't be used again, except maybe if
the runtime were re-initialized. In that case the sticky
situation would only happen if the module were re-imported
then and only if the subtype were stored in a global and only
if that global were not overwritten during import. We'd be
fine since the extension is otherwise unsafe and unsupported
in that situation, and likely problematic already.

In any case, this situation means at least some memory is
going to leak. This mostly only affects embedding scenarios.
*/

// For now we just clear tp_subclasses.

Py_CLEAR(type->tp_subclasses);
}

void
_PyStaticType_Dealloc(PyTypeObject *type)
{
type_dealloc_common(type);

Py_CLEAR(type->tp_dict);
Py_CLEAR(type->tp_bases);
Py_CLEAR(type->tp_mro);
Py_CLEAR(type->tp_cache);
// type->tp_subclasses is NULL
clear_static_tp_subclasses(type);

// PyObject_ClearWeakRefs() raises an exception if Py_REFCNT() != 0
if (Py_REFCNT(type) == 0) {
Expand Down