cpython: f0833e6ff2d2 (original) (raw)
Mercurial > cpython
changeset 83650:f0833e6ff2d2
Issue #1545463: Global variables caught in reference cycles are now garbage-collected at shutdown. [#1545463]
Antoine Pitrou solipsis@pitrou.net | |
---|---|
date | Mon, 06 May 2013 21:15:57 +0200 |
parents | 6d971b172389 |
children | 557599a32821 |
files | Include/pythonrun.h Lib/test/test_gc.py Misc/NEWS Modules/gcmodule.c Python/import.c Python/pythonrun.c |
diffstat | 6 files changed, 56 insertions(+), 5 deletions(-)[+] [-] Include/pythonrun.h 1 Lib/test/test_gc.py 36 Misc/NEWS 3 Modules/gcmodule.c 8 Python/import.c 8 Python/pythonrun.c 5 |
line wrap: on
line diff
--- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -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);
--- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -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[](#l2.17)
# it gets collected at interpreter shutdown.[](#l2.18)
code = """if 1:[](#l2.19)
import weakref[](#l2.20)
class C:[](#l2.21)
def __del__(self):[](#l2.22)
print('__del__ called')[](#l2.23)
l = [C()][](#l2.24)
l.append(l)[](#l2.25)
"""[](#l2.26)
rc, out, err = assert_python_ok('-c', code)[](#l2.27)
self.assertEqual(out.strip(), b'__del__ called')[](#l2.28)
- def test_gc_ordinary_module_at_shutdown(self):
# Same as above, but with a non-__main__ module.[](#l2.31)
with temp_dir() as script_dir:[](#l2.32)
module = """if 1:[](#l2.33)
import weakref[](#l2.34)
class C:[](#l2.35)
def __del__(self):[](#l2.36)
print('__del__ called')[](#l2.37)
l = [C()][](#l2.38)
l.append(l)[](#l2.39)
"""[](#l2.40)
code = """if 1:[](#l2.41)
import sys[](#l2.42)
sys.path.insert(0, %r)[](#l2.43)
import gctest[](#l2.44)
""" % (script_dir,)[](#l2.45)
make_script(script_dir, 'gctest', module)[](#l2.46)
rc, out, err = assert_python_ok('-c', code)[](#l2.47)
self.assertEqual(out.strip(), b'__del__ called')[](#l2.48)
+ def test_get_stats(self): stats = gc.get_stats() self.assertEqual(len(stats), 3)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -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
- 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
--- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -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 @@ void Py_XDECREF(bytes); } } +} + +void +_PyGC_Fini(void) +{ Py_CLEAR(callbacks); }
--- a/Python/import.c +++ b/Python/import.c @@ -403,6 +403,14 @@ PyImport_Cleanup(void) } }
- /* Collect garbage remaining after deleting the modules. Mostly
reference cycles created by classes. */[](#l5.8)
- PyGC_Collect();
- /* Dump GC stats before it's too late, since it uses the warnings
machinery. */[](#l5.12)
- _PyGC_DumpShutdownStats();
+ /* Next, delete sys and builtins (in that order) */ value = PyDict_GetItemString(modules, "sys"); if (value != NULL && PyModule_Check(value)) {
--- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -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 */[](#l6.8)
- _PyGC_Fini();
- /* Destroy all modules */ PyImport_Cleanup(); @@ -628,6 +624,7 @@ Py_Finalize(void) PyFloat_Fini(); PyDict_Fini(); PySlice_Fini();