@@ -1351,7 +1351,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
13511351 assert (PyType_Check (type ));
13521352 PySetObject * so ;
13531353
1354- so = (PySetObject * )type -> tp_alloc (type , 0 );
1354+ // Allocate untracked: the fill below runs user code, and a half-built
1355+ // set must not be reachable from another thread via gc.get_objects().
1356+ so = (PySetObject * )_PyType_AllocNoTrack (type , 0 );
13551357 if (so == NULL )
13561358 return NULL ;
13571359
@@ -1370,6 +1372,8 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
13701372 }
13711373 }
13721374
1375+ // Track only once fully built.
1376+ _PyObject_GC_TRACK (so );
13731377 return (PyObject * )so ;
13741378}
13751379
@@ -2885,7 +2889,7 @@ PyTypeObject PySet_Type = {
28852889 0 , /* tp_descr_set */
28862890 0 , /* tp_dictoffset */
28872891 set_init , /* tp_init */
2888- PyType_GenericAlloc , /* tp_alloc */
2892+ _PyType_AllocNoTrack , /* tp_alloc */
28892893 set_new , /* tp_new */
28902894 PyObject_GC_Del , /* tp_free */
28912895 .tp_vectorcall = set_vectorcall ,
@@ -2977,7 +2981,7 @@ PyTypeObject PyFrozenSet_Type = {
29772981 0 , /* tp_descr_set */
29782982 0 , /* tp_dictoffset */
29792983 0 , /* tp_init */
2980- PyType_GenericAlloc , /* tp_alloc */
2984+ _PyType_AllocNoTrack , /* tp_alloc */
29812985 frozenset_new , /* tp_new */
29822986 PyObject_GC_Del , /* tp_free */
29832987 .tp_vectorcall = frozenset_vectorcall ,
0 commit comments