(original) (raw)

changeset: 83835:5abe85aefe29 user: Antoine Pitrou solipsis@pitrou.net date: Sun May 19 01:11:58 2013 +0200 files: Include/objimpl.h Misc/NEWS Modules/gcmodule.c Python/import.c description: Issue #17937: Try harder to collect cyclic garbage at shutdown. diff -r e79df5d1f680 -r 5abe85aefe29 Include/objimpl.h --- a/Include/objimpl.h Sat May 18 15:47:58 2013 -0700 +++ b/Include/objimpl.h Sun May 19 01:11:58 2013 +0200 @@ -232,6 +232,10 @@ /* 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 -r e79df5d1f680 -r 5abe85aefe29 Misc/NEWS --- a/Misc/NEWS Sat May 18 15:47:58 2013 -0700 +++ b/Misc/NEWS Sun May 19 01:11:58 2013 +0200 @@ -10,6 +10,8 @@ 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 -r e79df5d1f680 -r 5abe85aefe29 Modules/gcmodule.c --- a/Modules/gcmodule.c Sat May 18 15:47:58 2013 -0700 +++ b/Modules/gcmodule.c Sun May 19 01:11:58 2013 +0200 @@ -853,7 +853,8 @@ /* 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 @@ } 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 @@ { 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 @@ 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 -r e79df5d1f680 -r 5abe85aefe29 Python/import.c --- a/Python/import.c Sat May 18 15:47:58 2013 -0700 +++ b/Python/import.c Sun May 19 01:11:58 2013 +0200 @@ -444,6 +444,7 @@ /* Finally, clear and delete the modules directory */ PyDict_Clear(modules); + _PyGC_CollectNoFail(); interp->modules = NULL; Py_DECREF(modules); } /solipsis@pitrou.net