Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b4f3a62

Browse filesBrowse files
miss-islingtonencukouhugovkericsnowcurrently
authored
[3.11] gh-110812: Isolating Extension Modules HOWTO: List GC-related gotchas (GH-111504) (GH-112147)
gh-110812: Isolating Extension Modules HOWTO: List GC-related gotchas (GH-111504) (cherry picked from commit 985679f) Co-authored-by: Petr Viktorin <encukou@gmail.com> Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Co-authored-by: Eric Snow <ericsnowcurrently@gmail.com>
1 parent 132a749 commit b4f3a62
Copy full SHA for b4f3a62

File tree

Expand file treeCollapse file tree

1 file changed

+97
-6
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+97
-6
lines changed

‎Doc/howto/isolating-extensions.rst

Copy file name to clipboardExpand all lines: Doc/howto/isolating-extensions.rst
+97-6Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -337,12 +337,44 @@ That is, heap types should:
337337
- Define a traverse function using ``Py_tp_traverse``, which
338338
visits the type (e.g. using :c:expr:`Py_VISIT(Py_TYPE(self))`).
339339

340-
Please refer to the :ref:`the documentation <type-structs>` of
340+
Please refer to the the documentation of
341341
:c:macro:`Py_TPFLAGS_HAVE_GC` and :c:member:`~PyTypeObject.tp_traverse`
342342
for additional considerations.
343343

344-
If your traverse function delegates to the ``tp_traverse`` of its base class
345-
(or another type), ensure that ``Py_TYPE(self)`` is visited only once.
344+
The API for defining heap types grew organically, leaving it
345+
somewhat awkward to use in its current state.
346+
The following sections will guide you through common issues.
347+
348+
349+
``tp_traverse`` in Python 3.8 and lower
350+
.......................................
351+
352+
The requirement to visit the type from ``tp_traverse`` was added in Python 3.9.
353+
If you support Python 3.8 and lower, the traverse function must *not*
354+
visit the type, so it must be more complicated::
355+
356+
static int my_traverse(PyObject *self, visitproc visit, void *arg)
357+
{
358+
if (Py_Version >= 0x03090000) {
359+
Py_VISIT(Py_TYPE(self));
360+
}
361+
return 0;
362+
}
363+
364+
Unfortunately, :c:data:`Py_Version` was only added in Python 3.11.
365+
As a replacement, use:
366+
367+
* :c:macro:`PY_VERSION_HEX`, if not using the stable ABI, or
368+
* :py:data:`sys.version_info` (via :c:func:`PySys_GetObject` and
369+
:c:func:`PyArg_ParseTuple`).
370+
371+
372+
Delegating ``tp_traverse``
373+
..........................
374+
375+
If your traverse function delegates to the :c:member:`~PyTypeObject.tp_traverse`
376+
of its base class (or another type), ensure that ``Py_TYPE(self)`` is visited
377+
only once.
346378
Note that only heap type are expected to visit the type in ``tp_traverse``.
347379

348380
For example, if your traverse function includes::
@@ -354,11 +386,70 @@ For example, if your traverse function includes::
354386
if (base->tp_flags & Py_TPFLAGS_HEAPTYPE) {
355387
// a heap type's tp_traverse already visited Py_TYPE(self)
356388
} else {
357-
Py_VISIT(Py_TYPE(self));
389+
if (Py_Version >= 0x03090000) {
390+
Py_VISIT(Py_TYPE(self));
391+
}
358392
}
359393

360-
It is not necessary to handle the type's reference count in ``tp_new``
361-
and ``tp_clear``.
394+
It is not necessary to handle the type's reference count in
395+
:c:member:`~PyTypeObject.tp_new` and :c:member:`~PyTypeObject.tp_clear`.
396+
397+
398+
Defining ``tp_dealloc``
399+
.......................
400+
401+
If your type has a custom :c:member:`~PyTypeObject.tp_dealloc` function,
402+
it needs to:
403+
404+
- call :c:func:`PyObject_GC_UnTrack` before any fields are invalidated, and
405+
- decrement the reference count of the type.
406+
407+
To keep the type valid while ``tp_free`` is called, the type's refcount needs
408+
to be decremented *after* the instance is deallocated. For example::
409+
410+
static void my_dealloc(PyObject *self)
411+
{
412+
PyObject_GC_UnTrack(self);
413+
...
414+
PyTypeObject *type = Py_TYPE(self);
415+
type->tp_free(self);
416+
Py_DECREF(type);
417+
}
418+
419+
The default ``tp_dealloc`` function does this, so
420+
if your type does *not* override
421+
``tp_dealloc`` you don't need to add it.
422+
423+
424+
Not overriding ``tp_free``
425+
..........................
426+
427+
The :c:member:`~PyTypeObject.tp_free` slot of a heap type must be set to
428+
:c:func:`PyObject_GC_Del`.
429+
This is the default; do not override it.
430+
431+
432+
Avoiding ``PyObject_New``
433+
.........................
434+
435+
GC-tracked objects need to be allocated using GC-aware functions.
436+
437+
If you use use :c:func:`PyObject_New` or :c:func:`PyObject_NewVar`:
438+
439+
- Get and call type's :c:member:`~PyTypeObject.tp_alloc` slot, if possible.
440+
That is, replace ``TYPE *o = PyObject_New(TYPE, typeobj)`` with::
441+
442+
TYPE *o = typeobj->tp_alloc(typeobj, 0);
443+
444+
Replace ``o = PyObject_NewVar(TYPE, typeobj, size)`` with the same,
445+
but use size instead of the 0.
446+
447+
- If the above is not possible (e.g. inside a custom ``tp_alloc``),
448+
call :c:func:`PyObject_GC_New` or :c:func:`PyObject_GC_NewVar`::
449+
450+
TYPE *o = PyObject_GC_New(TYPE, typeobj);
451+
452+
TYPE *o = PyObject_GC_NewVar(TYPE, typeobj, size);
362453

363454

364455
Module State Access from Classes

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.