@@ -1345,14 +1345,14 @@ set_update_impl(PySetObject *so, PyObject * const *others,
13451345 can be retrieved or updated in a single cache line.
13461346*/
13471347
1348+ // Build a set/frozenset left GC-untracked; the caller must _PyObject_GC_TRACK()
1349+ // it once fully built, so a half-built set is never exposed during filling.
13481350static PyObject *
1349- make_new_set (PyTypeObject * type , PyObject * iterable )
1351+ make_new_set_untracked (PyTypeObject * type , PyObject * iterable )
13501352{
13511353 assert (PyType_Check (type ));
13521354 PySetObject * so ;
13531355
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().
13561356 so = (PySetObject * )_PyType_AllocNoTrack (type , 0 );
13571357 if (so == NULL )
13581358 return NULL ;
@@ -1372,21 +1372,39 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
13721372 }
13731373 }
13741374
1375- // Track only once fully built.
1376- _PyObject_GC_TRACK (so );
13771375 return (PyObject * )so ;
13781376}
13791377
13801378static PyObject *
1381- make_new_set_basetype (PyTypeObject * type , PyObject * iterable )
1379+ make_new_set (PyTypeObject * type , PyObject * iterable )
1380+ {
1381+ PyObject * so = make_new_set_untracked (type , iterable );
1382+ if (so != NULL ) {
1383+ _PyObject_GC_TRACK (so );
1384+ }
1385+ return so ;
1386+ }
1387+
1388+ static PyObject *
1389+ make_new_set_basetype_untracked (PyTypeObject * type , PyObject * iterable )
13821390{
13831391 if (type != & PySet_Type && type != & PyFrozenSet_Type ) {
13841392 if (PyType_IsSubtype (type , & PySet_Type ))
13851393 type = & PySet_Type ;
13861394 else
13871395 type = & PyFrozenSet_Type ;
13881396 }
1389- return make_new_set (type , iterable );
1397+ return make_new_set_untracked (type , iterable );
1398+ }
1399+
1400+ static PyObject *
1401+ make_new_set_basetype (PyTypeObject * type , PyObject * iterable )
1402+ {
1403+ PyObject * so = make_new_set_basetype_untracked (type , iterable );
1404+ if (so != NULL ) {
1405+ _PyObject_GC_TRACK (so );
1406+ }
1407+ return so ;
13901408}
13911409
13921410// gh-140232: check whether a frozenset can be untracked from the GC
@@ -1686,7 +1704,7 @@ set_intersection(PySetObject *so, PyObject *other)
16861704 if ((PyObject * )so == other )
16871705 return set_copy_impl (so );
16881706
1689- result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
1707+ result = (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
16901708 if (result == NULL )
16911709 return NULL ;
16921710
@@ -1719,6 +1737,7 @@ set_intersection(PySetObject *so, PyObject *other)
17191737 }
17201738 Py_DECREF (key );
17211739 }
1740+ _PyObject_GC_TRACK (result );
17221741 return (PyObject * )result ;
17231742 }
17241743
@@ -1750,6 +1769,7 @@ set_intersection(PySetObject *so, PyObject *other)
17501769 Py_DECREF (result );
17511770 return NULL ;
17521771 }
1772+ _PyObject_GC_TRACK (result );
17531773 return (PyObject * )result ;
17541774 error :
17551775 Py_DECREF (it );
@@ -2064,7 +2084,7 @@ set_difference(PySetObject *so, PyObject *other)
20642084 return set_copy_and_difference (so , other );
20652085 }
20662086
2067- result = make_new_set_basetype (Py_TYPE (so ), NULL );
2087+ result = make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
20682088 if (result == NULL )
20692089 return NULL ;
20702090
@@ -2088,6 +2108,7 @@ set_difference(PySetObject *so, PyObject *other)
20882108 }
20892109 Py_DECREF (key );
20902110 }
2111+ _PyObject_GC_TRACK (result );
20912112 return result ;
20922113 }
20932114
@@ -2111,6 +2132,7 @@ set_difference(PySetObject *so, PyObject *other)
21112132 }
21122133 Py_DECREF (key );
21132134 }
2135+ _PyObject_GC_TRACK (result );
21142136 return result ;
21152137}
21162138
@@ -2312,7 +2334,8 @@ static PyObject *
23122334set_symmetric_difference_impl (PySetObject * so , PyObject * other )
23132335/*[clinic end generated code: output=270ee0b5d42b0797 input=8c29b0be90d47feb]*/
23142336{
2315- PySetObject * result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
2337+ PySetObject * result =
2338+ (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
23162339 if (result == NULL ) {
23172340 return NULL ;
23182341 }
@@ -2324,6 +2347,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other)
23242347 Py_DECREF (result );
23252348 return NULL ;
23262349 }
2350+ _PyObject_GC_TRACK (result );
23272351 return (PyObject * )result ;
23282352}
23292353
0 commit comments