Kaydet (Commit) 5c4bfc4a authored tarafından Benjamin Peterson's avatar Benjamin Peterson

prefer clearing global objects to obscure module.__dict__ bugs #10068

üst 11b1f3da
...@@ -654,6 +654,13 @@ Modules ...@@ -654,6 +654,13 @@ Modules
Special read-only attribute: :attr:`__dict__` is the module's namespace as a Special read-only attribute: :attr:`__dict__` is the module's namespace as a
dictionary object. dictionary object.
.. impl-detail::
Because of the way CPython clears module dictionaries, the module
dictionary will be cleared when the module falls out of scope even if the
dictionary still has live references. To avoid this, copy the dictionary
or keep the module around while using its dictionary directly.
.. index:: .. index::
single: __name__ (module attribute) single: __name__ (module attribute)
single: __doc__ (module attribute) single: __doc__ (module attribute)
......
# Test the module type # Test the module type
import unittest import unittest
from test.support import run_unittest from test.support import run_unittest, gc_collect
import sys import sys
ModuleType = type(sys) ModuleType = type(sys)
...@@ -55,14 +55,29 @@ class ModuleTests(unittest.TestCase): ...@@ -55,14 +55,29 @@ class ModuleTests(unittest.TestCase):
{"__name__": "foo", "__doc__": "foodoc", "bar": 42}) {"__name__": "foo", "__doc__": "foodoc", "bar": 42})
self.assertTrue(foo.__dict__ is d) self.assertTrue(foo.__dict__ is d)
@unittest.expectedFailure
def test_dont_clear_dict(self): def test_dont_clear_dict(self):
# See issue 7140. # See issue 7140.
def f(): def f():
foo = ModuleType("foo") foo = ModuleType("foo")
foo.bar = 4 foo.bar = 4
return foo return foo
gc_collect()
self.assertEqual(f().__dict__["bar"], 4) self.assertEqual(f().__dict__["bar"], 4)
def test_clear_dict_in_ref_cycle(self):
destroyed = []
m = ModuleType("foo")
m.destroyed = destroyed
s = """class A:
def __del__(self):
destroyed.append(1)
a = A()"""
exec(s, m.__dict__)
del m
gc_collect()
self.assertEqual(destroyed, [1])
def test_main(): def test_main():
run_unittest(ModuleTests) run_unittest(ModuleTests)
......
...@@ -37,6 +37,9 @@ What's New in Python 3.2 Alpha 3? ...@@ -37,6 +37,9 @@ What's New in Python 3.2 Alpha 3?
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #10068: Global objects which have reference cycles with their module's
dict are now cleared again. This causes issue #7140 to appear again.
- Issue #9738: Document PyErr_SetString() and PyErr_SetFromErrnoWithFilename() - Issue #9738: Document PyErr_SetString() and PyErr_SetFromErrnoWithFilename()
encodings. encodings.
......
...@@ -335,10 +335,7 @@ module_dealloc(PyModuleObject *m) ...@@ -335,10 +335,7 @@ module_dealloc(PyModuleObject *m)
if (m->md_def && m->md_def->m_free) if (m->md_def && m->md_def->m_free)
m->md_def->m_free(m); m->md_def->m_free(m);
if (m->md_dict != NULL) { if (m->md_dict != NULL) {
/* If we are the only ones holding a reference, we can clear _PyModule_Clear((PyObject *)m);
the dictionary. */
if (Py_REFCNT(m->md_dict) == 1)
_PyModule_Clear((PyObject *)m);
Py_DECREF(m->md_dict); Py_DECREF(m->md_dict);
} }
if (m->md_state != NULL) if (m->md_state != NULL)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment