Skip to content

Commit 619eac7

Browse files
committed
Use _DuringGC API in traversal functions
1 parent 0ae6c58 commit 619eac7

1 file changed

Lines changed: 35 additions & 8 deletions

File tree

Modules/xxlimited.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@
7272
pass
7373
*/
7474

75-
// Need limited C API version 3.15 for PyModExport
76-
#define Py_LIMITED_API 0x030f0000
77-
78-
// experimental: free-threaded build compatibility
79-
// (for internal tests; this should only appear here in CPython alpha builds)
80-
#define _Py_OPAQUE_PYOBJECT 0x030f0000
75+
// Target both flavors of the Stable ABI.
76+
// Both are set to version 3.15, which adds PyModExport
77+
// (When using a build tool, check if it has an option to set these
78+
// so they do not need to be defined in the source.)
79+
#define Py_LIMITED_API 0x030f0000 // abi3 (GIL-enabled builds)
80+
#define Py_TARGET_ABI3T 0x030f0000 // abi3t (free-threaded builds)
8181

8282

8383
#include "Python.h"
@@ -156,6 +156,27 @@ Xxo_get_data(PyObject *self)
156156
return data;
157157
}
158158

159+
// A variant of Xxo_get_data to be used in the tp_traverse handler.
160+
// This function cannot have side effects (including reference count
161+
// manipulation, creating objects, and raising exceptions), and must not
162+
// call API functions that might have side effects.
163+
// See: https://docs.python.org/3.15/c-api/gcsupport.html#traversal
164+
static XxoObject_Data *
165+
Xxo_get_data_DuringGC(PyObject *self)
166+
{
167+
PyTypeObject *base;
168+
PyType_GetBaseByToken_DuringGC(Py_TYPE(self), &Xxo_Type_spec, &base);
169+
if (base == NULL) {
170+
return NULL;
171+
}
172+
xx_state *state = PyType_GetModuleState_DuringGC(base);
173+
if (state == NULL) {
174+
return NULL;
175+
}
176+
XxoObject_Data *data = PyObject_GetTypeData_DuringGC(self, state->Xxo_Type);
177+
return data;
178+
}
179+
159180
// Xxo initialization
160181
// This is the implementation of Xxo.__new__
161182
static PyObject *
@@ -203,7 +224,7 @@ Xxo_traverse(PyObject *self, visitproc visit, void *arg)
203224
Py_VISIT(Py_TYPE(self));
204225

205226
// Visit the attribute dict
206-
XxoObject_Data *data = Xxo_get_data(self);
227+
XxoObject_Data *data = Xxo_get_data_DuringGC(self);
207228
if (data == NULL) {
208229
return 0;
209230
}
@@ -535,7 +556,10 @@ xx_modexec(PyObject *m)
535556
static int
536557
xx_traverse(PyObject *module, visitproc visit, void *arg)
537558
{
538-
xx_state *state = PyModule_GetState(module);
559+
xx_state *state = PyModule_GetState_DuringGC(module);
560+
if (state == NULL) {
561+
return 0;
562+
}
539563
Py_VISIT(state->Xxo_Type);
540564
Py_VISIT(state->Error_Type);
541565
return 0;
@@ -545,6 +569,9 @@ static int
545569
xx_clear(PyObject *module)
546570
{
547571
xx_state *state = PyModule_GetState(module);
572+
if (state == NULL) {
573+
return 0;
574+
}
548575
Py_CLEAR(state->Xxo_Type);
549576
Py_CLEAR(state->Error_Type);
550577
return 0;

0 commit comments

Comments
 (0)