@@ -1086,7 +1086,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
10861086 assert (PyType_Check (type ));
10871087 PySetObject * so ;
10881088
1089- so = (PySetObject * )type -> tp_alloc (type , 0 );
1089+ // Allocate untracked: the fill below runs user code, and a half-built
1090+ // set must not be reachable from another thread via gc.get_objects().
1091+ so = (PySetObject * )_PyType_AllocNoTrack (type , 0 );
10901092 if (so == NULL )
10911093 return NULL ;
10921094
@@ -1105,6 +1107,8 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
11051107 }
11061108 }
11071109
1110+ // Track only once fully built.
1111+ _PyObject_GC_TRACK (so );
11081112 return (PyObject * )so ;
11091113}
11101114
@@ -2499,7 +2503,7 @@ PyTypeObject PySet_Type = {
24992503 0 , /* tp_descr_set */
25002504 0 , /* tp_dictoffset */
25012505 (initproc )set_init , /* tp_init */
2502- PyType_GenericAlloc , /* tp_alloc */
2506+ _PyType_AllocNoTrack , /* tp_alloc */
25032507 set_new , /* tp_new */
25042508 PyObject_GC_Del , /* tp_free */
25052509 .tp_vectorcall = set_vectorcall ,
@@ -2590,7 +2594,7 @@ PyTypeObject PyFrozenSet_Type = {
25902594 0 , /* tp_descr_set */
25912595 0 , /* tp_dictoffset */
25922596 0 , /* tp_init */
2593- PyType_GenericAlloc , /* tp_alloc */
2597+ _PyType_AllocNoTrack , /* tp_alloc */
25942598 frozenset_new , /* tp_new */
25952599 PyObject_GC_Del , /* tp_free */
25962600 .tp_vectorcall = frozenset_vectorcall ,
0 commit comments