Skip to content

Commit 8923ca4

Browse files
encukoulysnikolaouvstinner
authored
gh-145921: Add "_DuringGC" functions for tp_traverse (GH-145925)
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 Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com> Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent 0b20bff commit 8923ca4

File tree

22 files changed

+445
-171
lines changed

22 files changed

+445
-171
lines changed

Doc/c-api/gcsupport.rst

Lines changed: 212 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -220,54 +220,237 @@ 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.
225+
226+
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:
224238
239+
Traversal
240+
---------
241+
242+
The :c:member:`~PyTypeObject.tp_traverse` handler must have the following type:
225243
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+
int err = PyObject_VisitManagedDict((PyObject*)self, visit, arg);
292+
if (err) {
293+
return err;
294+
}
295+
296+
Only the members that the instance *owns* (by having
297+
:term:`strong references <strong reference>` to them) must be
298+
visited. For instance, if an object supports weak references via the
299+
:c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting
300+
the linked list (what *tp_weaklist* points to) must **not** be
301+
visited as the instance does not directly own the weak references to itself.
302+
303+
The traversal function has a limitation:
304+
305+
.. warning::
306+
307+
The traversal function must not have any side effects. Implementations
308+
may not modify the reference counts of any Python objects nor create or
309+
destroy any Python objects, directly or indirectly.
310+
311+
This means that *most* Python C API functions may not be used, since
312+
they can raise a new exception, return a new reference to a result object,
313+
have internal logic that uses side effects.
314+
Also, unless documented otherwise, functions that happen to not have side
315+
effects may start having them in future versions, without warning.
316+
317+
For a list of safe functions, see a
318+
:ref:`separate section <duringgc-functions>` below.
319+
320+
.. note::
321+
322+
The :c:func:`Py_VISIT` call may be skipped for those members that provably
323+
cannot participate in reference cycles.
324+
In the ``local_traverse`` example above, there is also a ``self->key``
325+
member, but it can only be ``NULL`` or a Python string and therefore
326+
cannot be part of a reference cycle.
327+
328+
On the other hand, even if you know a member can never be part of a cycle,
329+
as a debugging aid you may want to visit it anyway just so the :mod:`gc`
330+
module's :func:`~gc.get_referents` function will include it.
331+
332+
.. note::
333+
334+
The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
335+
thread.
238336
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*:
337+
.. impl-detail::
242338
339+
Garbage collection is a "stop-the-world" operation:
340+
even in :term:`free threading` builds, only one thread state is
341+
:term:`attached <attached thread state>` when :c:member:`!tp_traverse`
342+
handlers run.
343+
344+
.. versionchanged:: 3.9
345+
346+
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
347+
``tp_traverse``. In earlier versions of Python, due to
348+
`bug 40217 <https://bugs.python.org/issue40217>`_, doing this
349+
may lead to crashes in subclasses.
350+
351+
To simplify writing :c:member:`~PyTypeObject.tp_traverse` handlers,
352+
a :c:func:`Py_VISIT` macro is provided.
353+
In order to use this macro, the :c:member:`~PyTypeObject.tp_traverse`
354+
implementation must name its arguments exactly *visit* and *arg*:
243355
244356
.. c:macro:: Py_VISIT(o)
245357
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::
358+
If the :c:expr:`PyObject *` *o* is not ``NULL``, call the *visit*
359+
callback, with arguments *o* and *arg*.
360+
If *visit* returns a non-zero value, then return it.
250361
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-
}
362+
This corresponds roughly to::
258363
259-
The :c:member:`~PyTypeObject.tp_clear` handler must be of the :c:type:`inquiry` type, or ``NULL``
260-
if the object is immutable.
364+
#define Py_VISIT(o) \
365+
if (op) { \
366+
int visit_result = visit(o, arg); \
367+
if (visit_result != 0) { \
368+
return visit_result; \
369+
} \
370+
}
261371
262372
263-
.. c:type:: int (*inquiry)(PyObject *self)
373+
Traversal-safe functions
374+
^^^^^^^^^^^^^^^^^^^^^^^^
264375
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.
376+
The following functions and macros are safe to use in a
377+
:c:member:`~PyTypeObject.tp_traverse` handler:
378+
379+
* the *visit* function passed to ``tp_traverse``
380+
* :c:func:`Py_VISIT`
381+
* :c:func:`Py_SIZE`
382+
* :c:func:`Py_TYPE`: if called from a :c:member:`!tp_traverse` handler,
383+
:c:func:`!Py_TYPE`'s result will be valid for the duration of the handler call
384+
* :c:func:`PyObject_VisitManagedDict`
385+
* :c:func:`PyObject_TypeCheck`, :c:func:`PyType_IsSubtype`,
386+
:c:func:`PyType_HasFeature`
387+
* :samp:`Py{<type>}_Check` and :samp:`Py{<type>}_CheckExact` -- for example,
388+
:c:func:`PyTuple_Check`
389+
* :ref:`duringgc-functions`
390+
391+
.. _duringgc-functions:
392+
393+
"DuringGC" functions
394+
^^^^^^^^^^^^^^^^^^^^
395+
396+
The following functions should *only* be used in a
397+
:c:member:`~PyTypeObject.tp_traverse` handler; calling them in other
398+
contexts may have unintended consequences.
399+
400+
These functions act like their counterparts without the ``_DuringGC`` suffix,
401+
but they are guaranteed to not have side effects, they do not set an exception
402+
on failure, and they return/set :term:`borrowed references <borrowed reference>`
403+
as detailed in the individual documentation.
404+
405+
Note that these functions may fail (return ``NULL`` or ``-1``),
406+
but as they do not set an exception, no error information is available.
407+
In some cases, failure is not distinguishable from a successful ``NULL`` result.
408+
409+
.. c:function:: void *PyObject_GetTypeData_DuringGC(PyObject *o, PyTypeObject *cls)
410+
void *PyObject_GetItemData_DuringGC(PyObject *o)
411+
void *PyType_GetModuleState_DuringGC(PyTypeObject *type)
412+
void *PyModule_GetState_DuringGC(PyObject *module)
413+
int PyModule_GetToken_DuringGC(PyObject *module, void** result)
414+
415+
See :ref:`duringgc-functions` for common information.
416+
417+
.. versionadded:: next
418+
419+
.. seealso::
420+
421+
:c:func:`PyObject_GetTypeData`,
422+
:c:func:`PyObject_GetItemData`,
423+
:c:func:`PyType_GetModuleState`,
424+
:c:func:`PyModule_GetState`,
425+
:c:func:`PyModule_GetToken`,
426+
:c:func:`PyType_GetBaseByToken`
427+
428+
.. c:function:: int PyType_GetBaseByToken_DuringGC(PyTypeObject *type, void *tp_token, PyTypeObject **result)
429+
430+
See :ref:`duringgc-functions` for common information.
431+
432+
Sets *\*result* to a :term:`borrowed reference` rather than a strong one.
433+
The reference is valid for the duration
434+
of the :c:member:`!tp_traverse` handler call.
435+
436+
.. versionadded:: next
437+
438+
.. seealso:: :c:func:`PyType_GetBaseByToken`
439+
440+
.. c:function:: PyObject* PyType_GetModule_DuringGC(PyTypeObject *type)
441+
PyObject* PyType_GetModuleByToken_DuringGC(PyTypeObject *type, const void *mod_token)
442+
443+
See :ref:`duringgc-functions` for common information.
444+
445+
These functions return a :term:`borrowed reference`, which is
446+
valid for the duration of the :c:member:`!tp_traverse` handler call.
447+
448+
.. versionadded:: next
449+
450+
.. seealso::
451+
452+
:c:func:`PyType_GetModule`,
453+
:c:func:`PyType_GetModuleByToken`
271454
272455
273456
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)