@@ -1006,12 +1006,14 @@ debug_cycle(const char *msg, PyObject *op)
10061006/* Call debug_cycle() on each object in `list`. sys.stderr.write() can run
10071007 * Python code that frees any object in the list, including the one just
10081008 * printed, so always take the first object and move it to a temporary
1009- * `seen` list, as finalize_garbage() does.
1009+ * `seen` list, as finalize_garbage() does. Return the number of seen
1010+ * items.
10101011 */
1011- static void
1012+ static int
10121013debug_cycles (const char * msg , PyGC_Head * list )
10131014{
10141015 PyGC_Head seen ;
1016+ Py_ssize_t n = 0 ;
10151017 /* Always take the next object from the head of `list` rather than from
10161018 * the current one, which may be freed (along with others) by debug_cycle().
10171019 */
@@ -1020,11 +1022,13 @@ debug_cycles(const char *msg, PyGC_Head *list)
10201022 PyGC_Head * gc = GC_NEXT (list );
10211023 PyObject * op = FROM_GC (gc );
10221024 gc_list_move (gc , & seen );
1025+ n ++ ;
10231026 Py_INCREF (op );
10241027 debug_cycle (msg , op );
10251028 Py_DECREF (op );
10261029 }
10271030 gc_list_merge (& seen , list );
1031+ return n ;
10281032}
10291033
10301034/* Handle uncollectable garbage (cycles with tp_del slots, and stuff reachable
@@ -1625,9 +1629,11 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
16251629 /* Collect statistics on uncollectable objects found and print
16261630 * debugging information. */
16271631 if (gcstate -> debug & _PyGC_DEBUG_UNCOLLECTABLE ) {
1628- debug_cycles ("uncollectable" , & finalizers );
1632+ stats .uncollectable = debug_cycles ("uncollectable" , & finalizers );
1633+ } else {
1634+ stats .uncollectable = gc_list_size (& finalizers );
16291635 }
1630- stats . uncollectable = gc_list_size ( & finalizers );
1636+
16311637 (void )PyTime_PerfCounterRaw (& stats .ts_stop );
16321638 stats .duration = PyTime_AsSecondsDouble (stats .ts_stop - stats .ts_start );
16331639 if (gcstate -> debug & _PyGC_DEBUG_STATS ) {
0 commit comments