@@ -1345,14 +1345,16 @@ set_update_impl(PySetObject *so, PyObject * const *others,
13451345 can be retrieved or updated in a single cache line.
13461346*/
13471347
1348+ // Allocate a set/frozenset and fill it from `iterable` (if any), leaving it
1349+ // GC-untracked: filling runs user code, so a half-built set must not be
1350+ // reachable from another thread via gc.get_objects(). The caller must
1351+ // _PyObject_GC_TRACK() it once it is fully built.
13481352static PyObject *
1349- make_new_set (PyTypeObject * type , PyObject * iterable )
1353+ make_new_set_untracked (PyTypeObject * type , PyObject * iterable )
13501354{
13511355 assert (PyType_Check (type ));
13521356 PySetObject * so ;
13531357
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().
13561358 so = (PySetObject * )_PyType_AllocNoTrack (type , 0 );
13571359 if (so == NULL )
13581360 return NULL ;
@@ -1372,21 +1374,39 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
13721374 }
13731375 }
13741376
1375- // Track only once fully built.
1376- _PyObject_GC_TRACK (so );
13771377 return (PyObject * )so ;
13781378}
13791379
13801380static PyObject *
1381- make_new_set_basetype (PyTypeObject * type , PyObject * iterable )
1381+ make_new_set (PyTypeObject * type , PyObject * iterable )
1382+ {
1383+ PyObject * so = make_new_set_untracked (type , iterable );
1384+ if (so != NULL ) {
1385+ _PyObject_GC_TRACK (so );
1386+ }
1387+ return so ;
1388+ }
1389+
1390+ static PyObject *
1391+ make_new_set_basetype_untracked (PyTypeObject * type , PyObject * iterable )
13821392{
13831393 if (type != & PySet_Type && type != & PyFrozenSet_Type ) {
13841394 if (PyType_IsSubtype (type , & PySet_Type ))
13851395 type = & PySet_Type ;
13861396 else
13871397 type = & PyFrozenSet_Type ;
13881398 }
1389- return make_new_set (type , iterable );
1399+ return make_new_set_untracked (type , iterable );
1400+ }
1401+
1402+ static PyObject *
1403+ make_new_set_basetype (PyTypeObject * type , PyObject * iterable )
1404+ {
1405+ PyObject * so = make_new_set_basetype_untracked (type , iterable );
1406+ if (so != NULL ) {
1407+ _PyObject_GC_TRACK (so );
1408+ }
1409+ return so ;
13901410}
13911411
13921412// gh-140232: check whether a frozenset can be untracked from the GC
@@ -1696,7 +1716,7 @@ set_intersection(PySetObject *so, PyObject *other)
16961716 if ((PyObject * )so == other )
16971717 return set_copy_impl (so );
16981718
1699- result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
1719+ result = (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
17001720 if (result == NULL )
17011721 return NULL ;
17021722
@@ -1729,6 +1749,7 @@ set_intersection(PySetObject *so, PyObject *other)
17291749 }
17301750 Py_DECREF (key );
17311751 }
1752+ _PyObject_GC_TRACK (result );
17321753 return (PyObject * )result ;
17331754 }
17341755
@@ -1760,6 +1781,7 @@ set_intersection(PySetObject *so, PyObject *other)
17601781 Py_DECREF (result );
17611782 return NULL ;
17621783 }
1784+ _PyObject_GC_TRACK (result );
17631785 return (PyObject * )result ;
17641786 error :
17651787 Py_DECREF (it );
@@ -2074,7 +2096,7 @@ set_difference(PySetObject *so, PyObject *other)
20742096 return set_copy_and_difference (so , other );
20752097 }
20762098
2077- result = make_new_set_basetype (Py_TYPE (so ), NULL );
2099+ result = make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
20782100 if (result == NULL )
20792101 return NULL ;
20802102
@@ -2098,6 +2120,7 @@ set_difference(PySetObject *so, PyObject *other)
20982120 }
20992121 Py_DECREF (key );
21002122 }
2123+ _PyObject_GC_TRACK (result );
21012124 return result ;
21022125 }
21032126
@@ -2121,6 +2144,7 @@ set_difference(PySetObject *so, PyObject *other)
21212144 }
21222145 Py_DECREF (key );
21232146 }
2147+ _PyObject_GC_TRACK (result );
21242148 return result ;
21252149}
21262150
@@ -2322,7 +2346,8 @@ static PyObject *
23222346set_symmetric_difference_impl (PySetObject * so , PyObject * other )
23232347/*[clinic end generated code: output=270ee0b5d42b0797 input=8c29b0be90d47feb]*/
23242348{
2325- PySetObject * result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
2349+ PySetObject * result =
2350+ (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
23262351 if (result == NULL ) {
23272352 return NULL ;
23282353 }
@@ -2334,6 +2359,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other)
23342359 Py_DECREF (result );
23352360 return NULL ;
23362361 }
2362+ _PyObject_GC_TRACK (result );
23372363 return (PyObject * )result ;
23382364}
23392365
0 commit comments