Skip to content

Commit 797312f

Browse files
lysnikolaouencukou
authored andcommitted
gh-145921: Add "_DuringGC" functions for tp_traverse
There are newly documented restrictions on tp_traverse: The traversal function must not have any side effects. It must not modify the reference counts of any Python objects nor create or destroy any Python objects. * Add several functions that are guaranteed side-effect-free, with a _DuringGC suffix. * Use these in ctypes * Consolidate tp_traverse docs in gcsupport.rst, moving unique content from typeobj.rst there
1 parent 79b91e7 commit 797312f

File tree

21 files changed

+417
-165
lines changed

21 files changed

+417
-165
lines changed

Doc/c-api/gcsupport.rst

Lines changed: 198 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -220,54 +220,223 @@ The :c:member:`~PyTypeObject.tp_traverse` handler accepts a function parameter o
220220
detection; it's not expected that users will need to write their own
221221
visitor functions.
222222
223-
The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type:
223+
The :c:member:`~PyTypeObject.tp_clear` handler must be of the :c:type:`inquiry` type, or ``NULL``
224+
if the object is immutable.
224225
225226
227+
.. c:type:: int (*inquiry)(PyObject *self)
228+
229+
Drop references that may have created reference cycles. Immutable objects
230+
do not have to define this method since they can never directly create
231+
reference cycles. Note that the object must still be valid after calling
232+
this method (don't just call :c:func:`Py_DECREF` on a reference). The
233+
collector will call this method if it detects that this object is involved
234+
in a reference cycle.
235+
236+
237+
.. _gc-traversal:
238+
239+
Traversal
240+
---------
241+
242+
The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type:
243+
226244
.. c:type:: int (*traverseproc)(PyObject *self, visitproc visit, void *arg)
227245
228-
Traversal function for a container object. Implementations must call the
246+
Traversal function for a garbage-collected object, used by the garbage
247+
collector to detect reference cycles.
248+
Implementations must call the
229249
*visit* function for each object directly contained by *self*, with the
230250
parameters to *visit* being the contained object and the *arg* value passed
231251
to the handler. The *visit* function must not be called with a ``NULL``
232-
object argument. If *visit* returns a non-zero value that value should be
252+
object argument. If *visit* returns a non-zero value, that value should be
233253
returned immediately.
234254
235-
The traversal function must not have any side effects. Implementations
236-
may not modify the reference counts of any Python objects nor create or
237-
destroy any Python objects.
255+
A typical :c:member:`!tp_traverse` function calls the :c:func:`Py_VISIT`
256+
convenience macro on each of the instance's members that are Python
257+
objects that the instance owns.
258+
For example, this is a (slightly outdated) traversal function for
259+
the :py:class:`threading.local` class::
260+
261+
static int
262+
local_traverse(PyObject *op, visitproc visit, void *arg)
263+
{
264+
localobject *self = (localobject *) op;
265+
Py_VISIT(Py_TYPE(self));
266+
Py_VISIT(self->args);
267+
Py_VISIT(self->kw);
268+
Py_VISIT(self->dict);
269+
return 0;
270+
}
271+
272+
.. note::
273+
:c:func:`Py_VISIT` requires the *visit* and *arg* parameters to
274+
:c:func:`!local_traverse` to have these specific names; don't name them just
275+
anything.
276+
277+
Instances of :ref:`heap-allocated types <heap-types>` hold a reference to
278+
their type. Their traversal function must therefore visit the type::
279+
280+
Py_VISIT(Py_TYPE(self));
281+
282+
Alternately, the type may delegate this responsibility by
283+
calling ``tp_traverse`` of a heap-allocated superclass (or another
284+
heap-allocated type, if applicable).
285+
If they do not, the type object may not be garbage-collected.
286+
287+
If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit is set in the
288+
:c:member:`~PyTypeObject.tp_flags` field, the traverse function must call
289+
:c:func:`PyObject_VisitManagedDict` like this::
290+
291+
PyObject_VisitManagedDict((PyObject*)self, visit, arg);
292+
293+
Only the members that the instance *owns* (by having
294+
:term:`strong references <strong reference>` to them) must be
295+
visited. For instance, if an object supports weak references via the
296+
:c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting
297+
the linked list (what *tp_weaklist* points to) must **not** be
298+
visited as the instance does not directly own the weak references to itself.
299+
300+
The traversal function has a limitation:
301+
302+
.. warning::
303+
304+
The traversal function must not have any side effects. Implementations
305+
may not modify the reference counts of any Python objects nor create or
306+
destroy any Python objects, directly or indirectly.
307+
308+
This means that *most* Python C API functions may not be used, since
309+
they can raise a new exception, return a new reference to a result object,
310+
have internal logic that uses side effects.
311+
Also, unless documented otherwise, functions that happen to not have side
312+
effects may start having them in future versions, without warning.
313+
314+
For a list of safe functions, see a
315+
:ref:`separate section <durniggc-functions>` below.
316+
317+
.. note::
318+
319+
The :c:func:`Py_VISIT` call may be skipped for those members that provably
320+
cannot participate in reference cycles.
321+
In the ``local_traverse`` example above, there is also a ``self->key``
322+
member, but it can only be ``NULL`` or a Python string and therefore
323+
cannot be part of a reference cycle.
238324
239-
To simplify writing :c:member:`~PyTypeObject.tp_traverse` handlers, a :c:func:`Py_VISIT` macro is
240-
provided. In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse` implementation
241-
must name its arguments exactly *visit* and *arg*:
325+
On the other hand, even if you know a member can never be part of a cycle,
326+
as a debugging aid you may want to visit it anyway just so the :mod:`gc`
327+
module's :func:`~gc.get_referents` function will include it.
242328
329+
.. note::
330+
331+
The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
332+
thread.
333+
334+
.. versionchanged:: 3.9
335+
336+
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
337+
``tp_traverse``. In earlier versions of Python, due to
338+
`bug 40217 <https://bugs.python.org/issue40217>`_, doing this
339+
may lead to crashes in subclasses.
340+
341+
To simplify writing :c:member:`~PyTypeObject.tp_traverse` handlers,
342+
a :c:func:`Py_VISIT` macro is provided.
343+
In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse`
344+
implementation must name its arguments exactly *visit* and *arg*:
243345
244346
.. c:macro:: Py_VISIT(o)
245347
246-
If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit* callback, with arguments *o*
247-
and *arg*. If *visit* returns a non-zero value, then return it.
248-
Using this macro, :c:member:`~PyTypeObject.tp_traverse` handlers
249-
look like::
348+
If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit*
349+
callback, with arguments *o* and *arg*.
350+
If *visit* returns a non-zero value, then return it.
250351
251-
static int
252-
my_traverse(Noddy *self, visitproc visit, void *arg)
253-
{
254-
Py_VISIT(self->foo);
255-
Py_VISIT(self->bar);
256-
return 0;
257-
}
352+
This corresponds roughly to::
258353
259-
The :c:member:`~PyTypeObject.tp_clear` handler must be of the :c:type:`inquiry` type, or ``NULL``
260-
if the object is immutable.
354+
#define Py_VISIT(o) \
355+
if (op) { \
356+
int visit_result = visit(o, arg); \
357+
if (visit_result != 0) { \
358+
return visit_result; \
359+
} \
360+
}
261361
362+
.. _durniggc-functions:
262363
263-
.. c:type:: int (*inquiry)(PyObject *self)
364+
Traversal-safe functions
365+
^^^^^^^^^^^^^^^^^^^^^^^^
264366
265-
Drop references that may have created reference cycles. Immutable objects
266-
do not have to define this method since they can never directly create
267-
reference cycles. Note that the object must still be valid after calling
268-
this method (don't just call :c:func:`Py_DECREF` on a reference). The
269-
collector will call this method if it detects that this object is involved
270-
in a reference cycle.
367+
The following functions and macros are safe to use in a
368+
:c:member:`~PyTypeObject.tp_traverse` handler:
369+
370+
* the *visit* function passed to ``tp_traverse``
371+
* :c:func:`Py_VISIT`
372+
* :c:func:`Py_SIZE`
373+
* :c:func:`Py_TYPE`
374+
* :c:func:`PyObject_VisitManagedDict`
375+
* :c:func:`PyObject_TypeCheck`, :c:func:`PyType_IsSubtype`,
376+
:c:func:`PyType_HasFeature`
377+
* :samp:`Py{<type>}_Check` and :samp:`Py{<type>}_CheckExact` -- for example,
378+
:c:func:`PyTuple_Check`
379+
380+
The following functions should *only* used in a
381+
:c:member:`~PyTypeObject.tp_traverse` handler; calling them in other
382+
contexts may have unintended consequences:
383+
384+
.. c:function:: void *PyObject_GetTypeData_DuringGC(PyObject *o, PyTypeObject *cls)
385+
void *PyObject_GetItemData_DuringGC(PyObject *o)
386+
void *PyType_GetModuleState_DuringGC(PyTypeObject *type)
387+
void *PyModule_GetState_DuringGC(PyObject *module)
388+
int PyModule_GetToken_DuringGC(PyObject *module, void** result)
389+
390+
These functions act like their counterparts without the ``_DuringGC`` suffix,
391+
but they are guaranteed to not have side effects, and they do not
392+
set an exception on failure.
393+
394+
Note that these functions may fail (return ``NULL`` or -1).
395+
Only creating and setting the exception is suppressed.
396+
397+
.. versionadded:: next
398+
399+
.. seealso::
400+
401+
:c:func:`PyObject_GetTypeData`,
402+
:c:func:`PyObject_GetItemData`,
403+
:c:func:`PyType_GetModuleState`,
404+
:c:func:`PyModule_GetState`,
405+
:c:func:`PyModule_GetToken`,
406+
:c:func:`PyType_GetBaseByToken`
407+
408+
.. c:function:: int PyType_GetBaseByToken_DuringGC(PyTypeObject *type, void *tp_token, PyTypeObject **result)
409+
410+
Acts like :c:func:`PyType_GetBaseByToken`,
411+
but is guaranteed to not have side effects, does not
412+
set an exception on failure, and sets *\*result* to
413+
a :term:`borrowed reference` rather than a strong one.
414+
The reference is valid for the duration
415+
of the :c:member:`!tp_traverse` handler call.
416+
417+
Note that this function may fail (return -1).
418+
Only creating and setting the exception is suppressed.
419+
420+
.. versionadded:: next
421+
422+
.. c:function:: PyObject* PyType_GetModule_DuringGC(PyTypeObject *type)
423+
PyObject* PyType_GetModuleByToken_DuringGC(PyTypeObject *type, const void *mod_token)
424+
425+
These functions act like their counterparts without the ``_DuringGC`` suffix,
426+
but they are guaranteed to not have side effects, they never set an
427+
exception on failure, and they return a :term:`borrowed reference`.
428+
The returned reference is valid for the duration
429+
of the :c:member:`!tp_traverse` handler call.
430+
431+
Note that these functions may fail (return ``NULL``).
432+
Only creating and setting the exception is suppressed.
433+
434+
.. versionadded:: next
435+
436+
.. seealso::
437+
438+
:c:func:`PyType_GetModule`,
439+
:c:func:`PyType_GetModuleByToken`
271440
272441
273442
Controlling the Garbage Collector State

Doc/c-api/typeobj.rst

Lines changed: 2 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,93 +1563,9 @@ and :c:data:`PyType_Type` effectively act as defaults.)
15631563
.. corresponding-type-slot:: Py_tp_traverse
15641564

15651565
An optional pointer to a traversal function for the garbage collector. This is
1566-
only used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set. The signature is::
1566+
only used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set.
15671567

1568-
int tp_traverse(PyObject *self, visitproc visit, void *arg);
1569-
1570-
More information about Python's garbage collection scheme can be found
1571-
in section :ref:`supporting-cycle-detection`.
1572-
1573-
The :c:member:`~PyTypeObject.tp_traverse` pointer is used by the garbage collector to detect
1574-
reference cycles. A typical implementation of a :c:member:`~PyTypeObject.tp_traverse` function
1575-
simply calls :c:func:`Py_VISIT` on each of the instance's members that are Python
1576-
objects that the instance owns. For example, this is function :c:func:`!local_traverse` from the
1577-
:mod:`!_thread` extension module::
1578-
1579-
static int
1580-
local_traverse(PyObject *op, visitproc visit, void *arg)
1581-
{
1582-
localobject *self = (localobject *) op;
1583-
Py_VISIT(self->args);
1584-
Py_VISIT(self->kw);
1585-
Py_VISIT(self->dict);
1586-
return 0;
1587-
}
1588-
1589-
Note that :c:func:`Py_VISIT` is called only on those members that can participate
1590-
in reference cycles. Although there is also a ``self->key`` member, it can only
1591-
be ``NULL`` or a Python string and therefore cannot be part of a reference cycle.
1592-
1593-
On the other hand, even if you know a member can never be part of a cycle, as a
1594-
debugging aid you may want to visit it anyway just so the :mod:`gc` module's
1595-
:func:`~gc.get_referents` function will include it.
1596-
1597-
Heap types (:c:macro:`Py_TPFLAGS_HEAPTYPE`) must visit their type with::
1598-
1599-
Py_VISIT(Py_TYPE(self));
1600-
1601-
It is only needed since Python 3.9. To support Python 3.8 and older, this
1602-
line must be conditional::
1603-
1604-
#if PY_VERSION_HEX >= 0x03090000
1605-
Py_VISIT(Py_TYPE(self));
1606-
#endif
1607-
1608-
If the :c:macro:`Py_TPFLAGS_MANAGED_DICT` bit is set in the
1609-
:c:member:`~PyTypeObject.tp_flags` field, the traverse function must call
1610-
:c:func:`PyObject_VisitManagedDict` like this::
1611-
1612-
PyObject_VisitManagedDict((PyObject*)self, visit, arg);
1613-
1614-
.. warning::
1615-
When implementing :c:member:`~PyTypeObject.tp_traverse`, only the
1616-
members that the instance *owns* (by having :term:`strong references
1617-
<strong reference>` to them) must be
1618-
visited. For instance, if an object supports weak references via the
1619-
:c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting
1620-
the linked list (what *tp_weaklist* points to) must **not** be
1621-
visited as the instance does not directly own the weak references to itself
1622-
(the weakreference list is there to support the weak reference machinery,
1623-
but the instance has no strong reference to the elements inside it, as they
1624-
are allowed to be removed even if the instance is still alive).
1625-
1626-
.. warning::
1627-
The traversal function must not have any side effects. It must not
1628-
modify the reference counts of any Python objects nor create or destroy
1629-
any Python objects.
1630-
1631-
Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to
1632-
:c:func:`!local_traverse` to have these specific names; don't name them just
1633-
anything.
1634-
1635-
Instances of :ref:`heap-allocated types <heap-types>` hold a reference to
1636-
their type. Their traversal function must therefore either visit
1637-
:c:func:`Py_TYPE(self) <Py_TYPE>`, or delegate this responsibility by
1638-
calling ``tp_traverse`` of another heap-allocated type (such as a
1639-
heap-allocated superclass).
1640-
If they do not, the type object may not be garbage-collected.
1641-
1642-
.. note::
1643-
1644-
The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
1645-
thread.
1646-
1647-
.. versionchanged:: 3.9
1648-
1649-
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
1650-
``tp_traverse``. In earlier versions of Python, due to
1651-
`bug 40217 <https://bugs.python.org/issue40217>`_, doing this
1652-
may lead to crashes in subclasses.
1568+
See :ref:`gc-traversal` for documentation.
16531569

16541570
**Inheritance:**
16551571

Doc/data/refcounts.dat

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,10 +2430,17 @@ PyType_GetName:PyTypeObject*:type:0:
24302430
PyType_GetModule:PyObject*::0:
24312431
PyType_GetModule:PyTypeObject*:type:0:
24322432

2433+
PyType_GetModule_DuringGC:PyObject*::0:
2434+
PyType_GetModule_DuringGC:PyTypeObject*:type:0:
2435+
24332436
PyType_GetModuleByToken:PyObject*::+1:
24342437
PyType_GetModuleByToken:PyTypeObject*:type:0:
24352438
PyType_GetModuleByToken:PyModuleDef*:def::
24362439

2440+
PyType_GetModuleByToken_DuringGC:PyObject*::0:
2441+
PyType_GetModuleByToken_DuringGC:PyTypeObject*:type:0:
2442+
PyType_GetModuleByToken_DuringGC:PyModuleDef*:mod_token::
2443+
24372444
PyType_GetModuleByDef:PyObject*::0:
24382445
PyType_GetModuleByDef:PyTypeObject*:type:0:
24392446
PyType_GetModuleByDef:PyModuleDef*:def::

0 commit comments

Comments
 (0)