summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/objimpl.h4
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/gcmodule.c31
-rw-r--r--Python/import.c1
4 files changed, 32 insertions, 6 deletions
diff --git a/Include/objimpl.h b/Include/objimpl.h
index b577be2..8f36360 100644
--- a/Include/objimpl.h
+++ b/Include/objimpl.h
@@ -232,6 +232,10 @@ PyAPI_FUNC(PyVarObject *) _PyObject_NewVar(PyTypeObject *, Py_ssize_t);
/* C equivalent of gc.collect(). */
PyAPI_FUNC(Py_ssize_t) PyGC_Collect(void);
+#ifndef Py_LIMITED_API
+PyAPI_FUNC(Py_ssize_t) _PyGC_CollectNoFail(void);
+#endif
+
/* Test if a type has a GC head */
#define PyType_IS_GC(t) PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
diff --git a/Misc/NEWS b/Misc/NEWS
index 2bc763f..a85bc94 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.4.0 Alpha 1?
Core and Builtins
-----------------
+- Issue #17937: Try harder to collect cyclic garbage at shutdown.
+
- Issue #12370: Prevent class bodies from interfering with the __class__
closure.
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index 4315d55..28417c2 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -853,7 +853,8 @@ get_time(void)
/* This is the main function. Read this to understand how the
* collection process works. */
static Py_ssize_t
-collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable)
+collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable,
+ int nofail)
{
int i;
Py_ssize_t m = 0; /* # objects collected */
@@ -1000,10 +1001,15 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable)
}
if (PyErr_Occurred()) {
- if (gc_str == NULL)
- gc_str = PyUnicode_FromString("garbage collection");
- PyErr_WriteUnraisable(gc_str);
- Py_FatalError("unexpected exception during garbage collection");
+ if (nofail) {
+ PyErr_Clear();
+ }
+ else {
+ if (gc_str == NULL)
+ gc_str = PyUnicode_FromString("garbage collection");
+ PyErr_WriteUnraisable(gc_str);
+ Py_FatalError("unexpected exception during garbage collection");
+ }
}
/* Update stats */
@@ -1062,7 +1068,7 @@ collect_with_callback(int generation)
{
Py_ssize_t result, collected, uncollectable;
invoke_gc_callback("start", generation, 0, 0);
- result = collect(generation, &collected, &uncollectable);
+ result = collect(generation, &collected, &uncollectable, 0);
invoke_gc_callback("stop", generation, collected, uncollectable);
return result;
}
@@ -1544,6 +1550,19 @@ PyGC_Collect(void)
return n;
}
+Py_ssize_t
+_PyGC_CollectNoFail(void)
+{
+ Py_ssize_t n;
+
+ /* This function should only be called on interpreter shutdown, and
+ therefore not recursively. */
+ assert(!collecting);
+ collecting = 1;
+ n = collect(NUM_GENERATIONS - 1, NULL, NULL, 1);
+ collecting = 0;
+ return n;
+}
void
_PyGC_DumpShutdownStats(void)
diff --git a/Python/import.c b/Python/import.c
index 1fbafec..a42b0f8 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -444,6 +444,7 @@ PyImport_Cleanup(void)
/* Finally, clear and delete the modules directory */
PyDict_Clear(modules);
+ _PyGC_CollectNoFail();
interp->modules = NULL;
Py_DECREF(modules);
}