Issue #17937: Try harder to collect cyclic garbage at shutdown.
This commit is contained in:
parent
20c1cdd64a
commit
fef34e3186
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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,11 +1001,16 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable)
|
|||
}
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
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 */
|
||||
if (n_collected)
|
||||
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue