@@ -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+
198249static int
199250gc_visit_callback_exit_early (PyObject * obj , void * arg )
200251 {
@@ -316,6 +367,7 @@ static PyType_Spec ObjExtraData_TypeSpec = {
316367static 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 },
0 commit comments