Skip to content
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

PEP 630: Add sections for 2 more gotchas #2450

Merged
merged 3 commits into from
Mar 21, 2022
Merged
Changes from all commits
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
55 changes: 55 additions & 0 deletions pep-0630.rst
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,46 @@ The class should generally be stored in *both* the module state (for
safe access from C) and the module's ``__dict__`` (for access from
Python code).


Garbage Collection Protocol
~~~~~~~~~~~~~~~~~~~~~~~~~~~

Instances of heap types hold a reference to their type.
This ensures that the type isn't destroyed before its instance,
but may result in reference cycles that need to be broken by the
garbage collector.

To avoid memory leaks, instances of heap types must implement the
garbage collection protocol.
That is, heap types should:

- Have the ``Py_TPFLAGS_HAVE_GC`` flag,
- Define a traverse function using ``Py_tp_traverse``, which
visits the type (e.g. using ``Py_VISIT(Py_TYPE(self));``).

Please refer to the documentation of ``Py_TPFLAGS_HAVE_GC`` and
``tp_traverse`` for additional considerations.

If your traverse function delegates to ``tp_traverse`` of its base class
(or another type), ensure that ``Py_TYPE(self)`` is visited only once.
Note that only heap type are expected to visit the type in ``tp_traverse``.

For example, if your traverse function includes::

base->tp_traverse(self, visit, arg)

...and ``base`` may be a static type, then it should also include::

if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
// a heap type's tp_traverse already visited Py_TYPE(self)
} else {
Py_VISIT(Py_TYPE(self));
}

It is not necessary to handle the type's reference count in ``tp_new``
and ``tp_clear``.


Module State Access from Classes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -494,6 +534,21 @@ module.
C memory layout.


Lifetime of the Module State
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a module object is garbage-collected, its module state is freed.
For each pointer to (a part of) the module state, you must hold a reference
to the module object.

Usually this is not an issue, because types created with
``PyType_FromModuleAndSpec``, and their instances, hold a reference
to the module.
However, you must be careful in reference counting when you reference
module state from other places, such as callbacks for external
libraries.


Open Issues
-----------

Expand Down