Issue #1545463: Global variables caught in reference cycles are now garbage-collected at shutdown.
This commit is contained in:
parent
1df37c657d
commit
5f454a07a0
|
@ -217,6 +217,7 @@ PyAPI_FUNC(void) PyBytes_Fini(void);
|
|||
PyAPI_FUNC(void) PyByteArray_Fini(void);
|
||||
PyAPI_FUNC(void) PyFloat_Fini(void);
|
||||
PyAPI_FUNC(void) PyOS_FiniInterrupts(void);
|
||||
PyAPI_FUNC(void) _PyGC_DumpShutdownStats(void);
|
||||
PyAPI_FUNC(void) _PyGC_Fini(void);
|
||||
PyAPI_FUNC(void) PySlice_Fini(void);
|
||||
PyAPI_FUNC(void) _PyType_Fini(void);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import unittest
|
||||
from test.support import (verbose, refcount_test, run_unittest,
|
||||
strip_python_stderr)
|
||||
from test.script_helper import assert_python_ok, make_script, temp_dir
|
||||
|
||||
import sys
|
||||
import time
|
||||
import gc
|
||||
|
@ -610,6 +612,40 @@ class GCTests(unittest.TestCase):
|
|||
stderr = run_command(code % "gc.DEBUG_SAVEALL")
|
||||
self.assertNotIn(b"uncollectable objects at shutdown", stderr)
|
||||
|
||||
def test_gc_main_module_at_shutdown(self):
|
||||
# Create a reference cycle through the __main__ module and check
|
||||
# it gets collected at interpreter shutdown.
|
||||
code = """if 1:
|
||||
import weakref
|
||||
class C:
|
||||
def __del__(self):
|
||||
print('__del__ called')
|
||||
l = [C()]
|
||||
l.append(l)
|
||||
"""
|
||||
rc, out, err = assert_python_ok('-c', code)
|
||||
self.assertEqual(out.strip(), b'__del__ called')
|
||||
|
||||
def test_gc_ordinary_module_at_shutdown(self):
|
||||
# Same as above, but with a non-__main__ module.
|
||||
with temp_dir() as script_dir:
|
||||
module = """if 1:
|
||||
import weakref
|
||||
class C:
|
||||
def __del__(self):
|
||||
print('__del__ called')
|
||||
l = [C()]
|
||||
l.append(l)
|
||||
"""
|
||||
code = """if 1:
|
||||
import sys
|
||||
sys.path.insert(0, %r)
|
||||
import gctest
|
||||
""" % (script_dir,)
|
||||
make_script(script_dir, 'gctest', module)
|
||||
rc, out, err = assert_python_ok('-c', code)
|
||||
self.assertEqual(out.strip(), b'__del__ called')
|
||||
|
||||
def test_get_stats(self):
|
||||
stats = gc.get_stats()
|
||||
self.assertEqual(len(stats), 3)
|
||||
|
|
|
@ -10,6 +10,9 @@ What's New in Python 3.4.0 Alpha 1?
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #1545463: Global variables caught in reference cycles are now
|
||||
garbage-collected at shutdown.
|
||||
|
||||
- Issue #17094: Clear stale thread states after fork(). Note that this
|
||||
is a potentially disruptive change since it may release some system
|
||||
resources which would otherwise remain perpetually alive (e.g. database
|
||||
|
|
|
@ -1544,8 +1544,9 @@ PyGC_Collect(void)
|
|||
return n;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_PyGC_Fini(void)
|
||||
_PyGC_DumpShutdownStats(void)
|
||||
{
|
||||
if (!(debug & DEBUG_SAVEALL)
|
||||
&& garbage != NULL && PyList_GET_SIZE(garbage) > 0) {
|
||||
|
@ -1574,6 +1575,11 @@ _PyGC_Fini(void)
|
|||
Py_XDECREF(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_PyGC_Fini(void)
|
||||
{
|
||||
Py_CLEAR(callbacks);
|
||||
}
|
||||
|
||||
|
|
|
@ -403,6 +403,14 @@ PyImport_Cleanup(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Collect garbage remaining after deleting the modules. Mostly
|
||||
reference cycles created by classes. */
|
||||
PyGC_Collect();
|
||||
|
||||
/* Dump GC stats before it's too late, since it uses the warnings
|
||||
machinery. */
|
||||
_PyGC_DumpShutdownStats();
|
||||
|
||||
/* Next, delete sys and builtins (in that order) */
|
||||
value = PyDict_GetItemString(modules, "sys");
|
||||
if (value != NULL && PyModule_Check(value)) {
|
||||
|
|
|
@ -544,10 +544,6 @@ Py_Finalize(void)
|
|||
while (PyGC_Collect() > 0)
|
||||
/* nothing */;
|
||||
#endif
|
||||
/* We run this while most interpreter state is still alive, so that
|
||||
debug information can be printed out */
|
||||
_PyGC_Fini();
|
||||
|
||||
/* Destroy all modules */
|
||||
PyImport_Cleanup();
|
||||
|
||||
|
@ -628,6 +624,7 @@ Py_Finalize(void)
|
|||
PyFloat_Fini();
|
||||
PyDict_Fini();
|
||||
PySlice_Fini();
|
||||
_PyGC_Fini();
|
||||
|
||||
/* Cleanup Unicode implementation */
|
||||
_PyUnicode_Fini();
|
||||
|
|
Loading…
Reference in New Issue