Skip to content

Commit bd7a76f

Browse files
DinoVmiss-islington
authored andcommitted
gh-156395: Report frozen objects on free-threaded GC build (GH-156396)
Report frozen objects on free-threaded GC build (cherry picked from commit 9036982) Co-authored-by: Dino Viehland <dinoviehland@meta.com>
1 parent cfaf610 commit bd7a76f

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
On the free-threaded build, :c:func:`PyUnstable_GC_VisitObjects` now also
2+
visits frozen objects (objects moved to the permanent generation by
3+
:func:`gc.freeze`), matching the behavior of the default build.

Modules/_testcapi/gc.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,57 @@ test_gc_visit_objects_basic(PyObject *Py_UNUSED(self),
195195
Py_RETURN_NONE;
196196
}
197197

198+
static int
199+
gc_call_no_args(const char *method)
200+
{
201+
PyObject *gc = PyImport_ImportModule("gc");
202+
if (gc == NULL) {
203+
return -1;
204+
}
205+
PyObject *res = PyObject_CallMethod(gc, method, NULL);
206+
Py_DECREF(gc);
207+
if (res == NULL) {
208+
return -1;
209+
}
210+
Py_DECREF(res);
211+
return 0;
212+
}
213+
214+
// gh-131740: frozen objects must be visited too.
215+
static PyObject *
216+
test_gc_visit_objects_frozen(PyObject *Py_UNUSED(self),
217+
PyObject *Py_UNUSED(ignored))
218+
{
219+
PyObject *obj;
220+
struct gc_visit_state_basic state;
221+
222+
obj = PyList_New(0);
223+
if (obj == NULL) {
224+
return NULL;
225+
}
226+
if (gc_call_no_args("freeze") < 0) {
227+
Py_DECREF(obj);
228+
return NULL;
229+
}
230+
state.target = obj;
231+
state.found = 0;
232+
233+
PyUnstable_GC_VisitObjects(gc_visit_callback_basic, &state);
234+
235+
int err = gc_call_no_args("unfreeze");
236+
Py_DECREF(obj);
237+
if (err < 0) {
238+
return NULL;
239+
}
240+
if (!state.found) {
241+
PyErr_SetString(
242+
PyExc_AssertionError,
243+
"test_gc_visit_objects_frozen: Didn't find frozen list");
244+
return NULL;
245+
}
246+
Py_RETURN_NONE;
247+
}
248+
198249
static int
199250
gc_visit_callback_exit_early(PyObject *obj, void *arg)
200251
{
@@ -316,6 +367,7 @@ static PyType_Spec ObjExtraData_TypeSpec = {
316367
static PyMethodDef test_methods[] = {
317368
{"test_gc_control", test_gc_control, METH_NOARGS},
318369
{"test_gc_visit_objects_basic", test_gc_visit_objects_basic, METH_NOARGS, NULL},
370+
{"test_gc_visit_objects_frozen", test_gc_visit_objects_frozen, METH_NOARGS, NULL},
319371
{"test_gc_visit_objects_exit_early", test_gc_visit_objects_exit_early, METH_NOARGS, NULL},
320372
{"without_gc", without_gc, METH_O, NULL},
321373
{"with_tp_del", with_tp_del, METH_VARARGS, NULL},

Python/gc_free_threading.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2854,7 +2854,7 @@ static bool
28542854
custom_visitor_wrapper(const mi_heap_t *heap, const mi_heap_area_t *area,
28552855
void *block, size_t block_size, void *args)
28562856
{
2857-
PyObject *op = op_from_block(block, args, false);
2857+
PyObject *op = op_from_block(block, args, true);
28582858
if (op == NULL) {
28592859
return true;
28602860
}

0 commit comments

Comments
 (0)