@@ -654,6 +654,7 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
654
654
{
655
655
PyGC_Head * gc = finalizers -> gc .gc_next ;
656
656
657
+ assert (!PyErr_Occurred ());
657
658
if (_PyRuntime .gc .garbage == NULL ) {
658
659
_PyRuntime .gc .garbage = PyList_New (0 );
659
660
if (_PyRuntime .gc .garbage == NULL )
@@ -663,8 +664,10 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
663
664
PyObject * op = FROM_GC (gc );
664
665
665
666
if ((_PyRuntime .gc .debug & DEBUG_SAVEALL ) || has_legacy_finalizer (op )) {
666
- if (PyList_Append (_PyRuntime .gc .garbage , op ) < 0 )
667
+ if (PyList_Append (_PyRuntime .gc .garbage , op ) < 0 ) {
668
+ PyErr_Clear ();
667
669
break ;
670
+ }
668
671
}
669
672
}
670
673
@@ -701,6 +704,7 @@ finalize_garbage(PyGC_Head *collectable)
701
704
_PyGCHead_SET_FINALIZED (gc , 1 );
702
705
Py_INCREF (op );
703
706
finalize (op );
707
+ assert (!PyErr_Occurred ());
704
708
Py_DECREF (op );
705
709
}
706
710
}
@@ -748,17 +752,26 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
748
752
{
749
753
inquiry clear ;
750
754
755
+ assert (!PyErr_Occurred ());
751
756
while (!gc_list_is_empty (collectable )) {
752
757
PyGC_Head * gc = collectable -> gc .gc_next ;
753
758
PyObject * op = FROM_GC (gc );
754
759
755
760
if (_PyRuntime .gc .debug & DEBUG_SAVEALL ) {
756
- PyList_Append (_PyRuntime .gc .garbage , op );
761
+ assert (_PyRuntime .gc .garbage != NULL );
762
+ if (PyList_Append (_PyRuntime .gc .garbage , op ) < 0 ) {
763
+ PyErr_Clear ();
764
+ }
757
765
}
758
766
else {
759
767
if ((clear = Py_TYPE (op )-> tp_clear ) != NULL ) {
760
768
Py_INCREF (op );
761
- clear (op );
769
+ (void ) clear (op );
770
+ if (PyErr_Occurred ()) {
771
+ PySys_WriteStderr ("Exception ignored in tp_clear of "
772
+ "%.50s\n" , Py_TYPE (op )-> tp_name );
773
+ PyErr_WriteUnraisable (NULL );
774
+ }
762
775
Py_DECREF (op );
763
776
}
764
777
}
@@ -974,6 +987,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
974
987
if (PyDTrace_GC_DONE_ENABLED ())
975
988
PyDTrace_GC_DONE (n + m );
976
989
990
+ assert (!PyErr_Occurred ());
977
991
return n + m ;
978
992
}
979
993
@@ -987,11 +1001,12 @@ invoke_gc_callback(const char *phase, int generation,
987
1001
Py_ssize_t i ;
988
1002
PyObject * info = NULL ;
989
1003
1004
+ assert (!PyErr_Occurred ());
990
1005
/* we may get called very early */
991
1006
if (_PyRuntime .gc .callbacks == NULL )
992
1007
return ;
993
1008
/* The local variable cannot be rebound, check it for sanity */
994
- assert (_PyRuntime . gc . callbacks != NULL && PyList_CheckExact (_PyRuntime .gc .callbacks ));
1009
+ assert (PyList_CheckExact (_PyRuntime .gc .callbacks ));
995
1010
if (PyList_GET_SIZE (_PyRuntime .gc .callbacks ) != 0 ) {
996
1011
info = Py_BuildValue ("{sisnsn}" ,
997
1012
"generation" , generation ,
@@ -1015,6 +1030,7 @@ invoke_gc_callback(const char *phase, int generation,
1015
1030
Py_DECREF (cb );
1016
1031
}
1017
1032
Py_XDECREF (info );
1033
+ assert (!PyErr_Occurred ());
1018
1034
}
1019
1035
1020
1036
/* Perform garbage collection of a generation and invoke
@@ -1024,9 +1040,11 @@ static Py_ssize_t
1024
1040
collect_with_callback (int generation )
1025
1041
{
1026
1042
Py_ssize_t result , collected , uncollectable ;
1043
+ assert (!PyErr_Occurred ());
1027
1044
invoke_gc_callback ("start" , generation , 0 , 0 );
1028
1045
result = collect (generation , & collected , & uncollectable , 0 );
1029
1046
invoke_gc_callback ("stop" , generation , collected , uncollectable );
1047
+ assert (!PyErr_Occurred ());
1030
1048
return result ;
1031
1049
}
1032
1050
@@ -1592,6 +1610,7 @@ _PyGC_CollectNoFail(void)
1592
1610
{
1593
1611
Py_ssize_t n ;
1594
1612
1613
+ assert (!PyErr_Occurred ());
1595
1614
/* Ideally, this function is only called on interpreter shutdown,
1596
1615
and therefore not recursively. Unfortunately, when there are daemon
1597
1616
threads, a daemon thread can start a cyclic garbage collection
0 commit comments