File tree Expand file tree Collapse file tree
Misc/NEWS.d/next/Core_and_Builtins Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1662,6 +1662,25 @@ def test_indirect_calls_with_gc_disabled(self):
16621662 finally :
16631663 gc .enable ()
16641664
1665+ def test_get_count_nonnegative (self ):
1666+ xs = [[] for _ in range (1500 )]
1667+ gc .collect ()
1668+ del xs [:1000 ]
1669+ self .assertGreaterEqual (gc .get_count ()[0 ], 0 )
1670+
1671+ @gc_threshold (1000 , 0 , 0 )
1672+ def test_get_count_does_not_prevent_collection (self ):
1673+ junk = []
1674+ gc .collect ()
1675+ detector = GC_Detector ()
1676+ for _ in range (10000 ):
1677+ junk .append ([])
1678+ gc .get_count ()
1679+ if detector .gc_happened :
1680+ break
1681+ else :
1682+ self .fail ("gc didn't happen after 10000 iterations" )
1683+
16651684 # Ensure that setting *threshold0* to zero disables collection.
16661685 @gc_threshold (0 )
16671686 def test_threshold_zero (self ):
Original file line number Diff line number Diff line change 1+ Fix :func: `gc.get_count ` on the free-threaded build resetting the thread-local
2+ allocation counter that schedules automatic garbage collection. A thread that
3+ called it while allocating could prevent cyclic garbage from ever being
4+ collected.
Original file line number Diff line number Diff line change @@ -221,9 +221,12 @@ gc_get_count_impl(PyObject *module)
221221 _PyThreadStateImpl * tstate = (_PyThreadStateImpl * )_PyThreadState_GET ();
222222 struct _gc_thread_state * gc = & tstate -> gc ;
223223
224- // Flush the local allocation count to the global count
225- _Py_atomic_add_int (& gcstate -> young .count , (int )gc -> alloc_count );
226- gc -> alloc_count = 0 ;
224+ // Don't flush: record_allocation() checks the threshold only when it fills.
225+ int young = _Py_atomic_load_int_relaxed (& gcstate -> young .count );
226+ young += (int )gc -> alloc_count ;
227+ if (young < 0 ) {
228+ young = 0 ;
229+ }
227230#endif
228231
229232#ifndef Py_GIL_DISABLED
@@ -233,7 +236,7 @@ gc_get_count_impl(PyObject *module)
233236 gcstate -> generations [2 ].count );
234237#else
235238 return Py_BuildValue ("(iii)" ,
236- _Py_atomic_load_int_relaxed ( & gcstate -> young . count ) ,
239+ young ,
237240 gcstate -> old [0 ].count ,
238241 gcstate -> old [1 ].count );
239242#endif
You can’t perform that action at this time.
0 commit comments