@@ -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
@@ -1696,7 +1714,7 @@ set_intersection(PySetObject *so, PyObject *other)
16961714 if ((PyObject * )so == other )
16971715 return set_copy_impl (so );
16981716
1699- result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
1717+ result = (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
17001718 if (result == NULL )
17011719 return NULL ;
17021720
@@ -1729,6 +1747,7 @@ set_intersection(PySetObject *so, PyObject *other)
17291747 }
17301748 Py_DECREF (key );
17311749 }
1750+ _PyObject_GC_TRACK (result );
17321751 return (PyObject * )result ;
17331752 }
17341753
@@ -1760,6 +1779,7 @@ set_intersection(PySetObject *so, PyObject *other)
17601779 Py_DECREF (result );
17611780 return NULL ;
17621781 }
1782+ _PyObject_GC_TRACK (result );
17631783 return (PyObject * )result ;
17641784 error :
17651785 Py_DECREF (it );
@@ -2074,7 +2094,7 @@ set_difference(PySetObject *so, PyObject *other)
20742094 return set_copy_and_difference (so , other );
20752095 }
20762096
2077- result = make_new_set_basetype (Py_TYPE (so ), NULL );
2097+ result = make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
20782098 if (result == NULL )
20792099 return NULL ;
20802100
@@ -2098,6 +2118,7 @@ set_difference(PySetObject *so, PyObject *other)
20982118 }
20992119 Py_DECREF (key );
21002120 }
2121+ _PyObject_GC_TRACK (result );
21012122 return result ;
21022123 }
21032124
@@ -2121,6 +2142,7 @@ set_difference(PySetObject *so, PyObject *other)
21212142 }
21222143 Py_DECREF (key );
21232144 }
2145+ _PyObject_GC_TRACK (result );
21242146 return result ;
21252147}
21262148
@@ -2322,7 +2344,8 @@ static PyObject *
23222344set_symmetric_difference_impl (PySetObject * so , PyObject * other )
23232345/*[clinic end generated code: output=270ee0b5d42b0797 input=8c29b0be90d47feb]*/
23242346{
2325- PySetObject * result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
2347+ PySetObject * result =
2348+ (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
23262349 if (result == NULL ) {
23272350 return NULL ;
23282351 }
@@ -2334,6 +2357,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other)
23342357 Py_DECREF (result );
23352358 return NULL ;
23362359 }
2360+ _PyObject_GC_TRACK (result );
23372361 return (PyObject * )result ;
23382362}
23392363
0 commit comments