]> granicus.if.org Git - python/commitdiff
Issue #17937: Try harder to collect cyclic garbage at shutdown.
authorAntoine Pitrou <solipsis@pitrou.net>
Sat, 18 May 2013 23:11:58 +0000 (01:11 +0200)
committerAntoine Pitrou <solipsis@pitrou.net>
Sat, 18 May 2013 23:11:58 +0000 (01:11 +0200)
Include/objimpl.h
Misc/NEWS
Modules/gcmodule.c
Python/import.c

index b577be2df3b5fd0a7527fa15176d445c5048e796..8f36360bbf2ee95d2fce5a717e7b8719a6afe91b 100644 (file)
@@ -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)
 
index 2bc763f99aa5d6d335aaa6abbeb6adbee591d83b..a85bc9490c7c281ceb2dacdeda8da50b5b370324 100644 (file)
--- 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.
 
index 4315d55dcdb9c19adafb1082fdf6cbf660ff0663..28417c28fe5b1d6bcac2863f7a1fd0d1a6765ab2 100644 (file)
@@ -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)
index 1fbafecc1b70b62ed24035dfe99758fd25c285d1..a42b0f89b0a24291020b58a2c6726c90c10d6630 100644 (file)
@@ -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);
 }