Skip to content

Commit f582b75

Browse files
[2.7] bpo-33622: Fix issues with handling errors in the GC. (pythonGH-7078)
* Fixed a leak when the GC fails to add an object with __del__ into the gc.garbage list. * PyGC_Collect() can now be called when an exception is set and preserves it. (cherry picked from commit 301e3cc) Co-authored-by: Serhiy Storchaka <[email protected]>
1 parent 8cbde8a commit f582b75

File tree

2 files changed

+10
-6
lines changed

2 files changed

+10
-6
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixed a leak when the garbage collector fails to add an object with the
2+
``__del__`` method or referenced by it into the :data:`gc.garbage` list.
3+
:c:func:`PyGC_Collect` can now be called when an exception is set and
4+
preserves it.

Modules/gcmodule.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -771,10 +771,8 @@ debug_cycle(char *msg, PyObject *op)
771771
* garbage list (a Python list), else only the objects in finalizers with
772772
* __del__ methods are appended to garbage. All objects in finalizers are
773773
* merged into the old list regardless.
774-
* Returns 0 if all OK, <0 on error (out of memory to grow the garbage list).
775-
* The finalizers list is made empty on a successful return.
776774
*/
777-
static int
775+
static void
778776
handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
779777
{
780778
PyGC_Head *gc = finalizers->gc.gc_next;
@@ -789,12 +787,11 @@ handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
789787

790788
if ((debug & DEBUG_SAVEALL) || has_finalizer(op)) {
791789
if (PyList_Append(garbage, op) < 0)
792-
return -1;
790+
break;
793791
}
794792
}
795793

796794
gc_list_merge(finalizers, old);
797-
return 0;
798795
}
799796

800797
/* Break reference cycles by clearing the containers involved. This is
@@ -1012,7 +1009,7 @@ collect(int generation)
10121009
* reachable list of garbage. The programmer has to deal with
10131010
* this if they insist on creating this type of structure.
10141011
*/
1015-
(void)handle_finalizers(&finalizers, old);
1012+
handle_finalizers(&finalizers, old);
10161013

10171014
/* Clear free list only during the collection of the highest
10181015
* generation */
@@ -1436,8 +1433,11 @@ PyGC_Collect(void)
14361433
if (collecting)
14371434
n = 0; /* already collecting, don't do anything */
14381435
else {
1436+
PyObject *exc, *value, *tb;
14391437
collecting = 1;
1438+
PyErr_Fetch(&exc, &value, &tb);
14401439
n = collect(NUM_GENERATIONS - 1);
1440+
PyErr_Restore(exc, value, tb);
14411441
collecting = 0;
14421442
}
14431443

0 commit comments

Comments
 (0)