Skip to content

Commit fef34e3

Browse files
committed
Issue python#17937: Try harder to collect cyclic garbage at shutdown.
1 parent 20c1cdd commit fef34e3

File tree

4 files changed

+32
-6
lines changed

4 files changed

+32
-6
lines changed

Include/objimpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,10 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
232232
/* C equivalent of gc.collect(). */
233233
PyAPI_FUNC(Py_ssize_t) PyGC_Collect(void);
234234

235+
#ifndef Py_LIMITED_API
236+
PyAPI_FUNC(Py_ssize_t) _PyGC_CollectNoFail(void);
237+
#endif
238+
235239
/* Test if a type has a GC head */
236240
#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
237241

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #17937: Try harder to collect cyclic garbage at shutdown.
14+
1315
- Issue #12370: Prevent class bodies from interfering with the __class__
1416
closure.
1517

Modules/gcmodule.c

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,8 @@ get_time(void)
853853
/* This is the main function. Read this to understand how the
854854
* collection process works. */
855855
static Py_ssize_t
856-
collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable)
856+
collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
857+
int nofail)
857858
{
858859
int i;
859860
Py_ssize_t m = 0; /* # objects collected */
@@ -1000,10 +1001,15 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable)
10001001
}
10011002

10021003
if (PyErr_Occurred()) {
1003-
if (gc_str == NULL)
1004-
gc_str = PyUnicode_FromString("garbage collection");
1005-
PyErr_WriteUnraisable(gc_str);
1006-
Py_FatalError("unexpected exception during garbage collection");
1004+
if (nofail) {
1005+
PyErr_Clear();
1006+
}
1007+
else {
1008+
if (gc_str == NULL)
1009+
gc_str = PyUnicode_FromString("garbage collection");
1010+
PyErr_WriteUnraisable(gc_str);
1011+
Py_FatalError("unexpected exception during garbage collection");
1012+
}
10071013
}
10081014

10091015
/* Update stats */
@@ -1062,7 +1068,7 @@ collect_with_callback(int generation)
10621068
{
10631069
Py_ssize_t result, collected, uncollectable;
10641070
invoke_gc_callback("start", generation, 0, 0);
1065-
result = collect(generation, &collected, &uncollectable);
1071+
result = collect(generation, &collected, &uncollectable, 0);
10661072
invoke_gc_callback("stop", generation, collected, uncollectable);
10671073
return result;
10681074
}
@@ -1544,6 +1550,19 @@ PyGC_Collect(void)
15441550
return n;
15451551
}
15461552

1553+
Py_ssize_t
1554+
_PyGC_CollectNoFail(void)
1555+
{
1556+
Py_ssize_t n;
1557+
1558+
/* This function should only be called on interpreter shutdown, and
1559+
therefore not recursively. */
1560+
assert(!collecting);
1561+
collecting = 1;
1562+
n = collect(NUM_GENERATIONS - 1, NULL, NULL, 1);
1563+
collecting = 0;
1564+
return n;
1565+
}
15471566

15481567
void
15491568
_PyGC_DumpShutdownStats(void)

Python/import.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ PyImport_Cleanup(void)
444444

445445
/* Finally, clear and delete the modules directory */
446446
PyDict_Clear(modules);
447+
_PyGC_CollectNoFail();
447448
interp->modules = NULL;
448449
Py_DECREF(modules);
449450
}

0 commit comments

Comments
 (0)