summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Wouters <thomas@python.org>2006-04-15 23:27:28 (GMT)
committerThomas Wouters <thomas@python.org>2006-04-15 23:27:28 (GMT)
commitb8f81d48634ccee8a8a4089d04b81e1aadbc04fe (patch)
tree7fb3fe9a004e165a0847388d893a380522cc23a0
parent81b092d0e60db093c8ed2637deea545cb1de471a (diff)
downloadcpython-b8f81d48634ccee8a8a4089d04b81e1aadbc04fe.zip
cpython-b8f81d48634ccee8a8a4089d04b81e1aadbc04fe.tar.gz
cpython-b8f81d48634ccee8a8a4089d04b81e1aadbc04fe.tar.bz2
Add missing DECREF to PyErr_WriteUnraisable(). That function reports
exceptions that can't be raised any further, because (for instance) they occur in __del__ methods. The coroutine tests in test_generators was triggering this leak. Remove the leakers' testcase, and add a simpler testcase that explicitly tests this leak to test_generators. test_generators now no longer leaks at all, on my machine. This fix may also solve other leaks, but my full refleakhunting run is still busy, so who knows?
-rw-r--r--Lib/test/leakers/test_gen1.py19
-rw-r--r--Lib/test/test_generators.py36
-rw-r--r--Python/errors.c1
3 files changed, 35 insertions, 21 deletions
diff --git a/Lib/test/leakers/test_gen1.py b/Lib/test/leakers/test_gen1.py
deleted file mode 100644
index 72f644d..0000000
--- a/Lib/test/leakers/test_gen1.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import gc
-
-# Taken from test_generators
-
-def f():
- try:
- yield
- except GeneratorExit:
- yield "foo!"
-
-def inner_leak():
- g = f()
- g.next()
-
-def leak():
- inner_leak()
- gc.collect()
- gc.collect()
- gc.collect()
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index 67781c9..a60a768 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -1745,8 +1745,40 @@ was removed.
>>> leak()
-There should be more test_generator-induced refleaks here, after they get
-fixed.
+
+This test isn't really generator related, but rather exception-in-cleanup
+related. The coroutine tests (above) just happen to cause an exception in
+the generator's __del__ (tp_del) method. We can also test for this
+explicitly, without generators. We do have to redirect stderr to avoid
+printing warnings and to doublecheck that we actually tested what we wanted
+to test.
+
+>>> import sys, StringIO
+>>> old = sys.stderr
+>>> try:
+... sys.stderr = StringIO.StringIO()
+... class Leaker:
+... def __del__(self):
+... raise RuntimeError
+...
+... l = Leaker()
+... del l
+... err = sys.stderr.getvalue().strip()
+... err.startswith(
+... "Exception exceptions.RuntimeError: RuntimeError() in <"
+... )
+... err.endswith("> ignored")
+... len(err.splitlines())
+... finally:
+... sys.stderr = old
+True
+True
+1
+
+
+
+These refleak tests should perhaps be in a testfile of their own,
+test_generators just happened to be the test that drew these out.
"""
diff --git a/Python/errors.c b/Python/errors.c
index 25deaa6..275a065 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -604,6 +604,7 @@ PyErr_WriteUnraisable(PyObject *obj)
PyFile_WriteString(": ", f);
PyFile_WriteObject(v, f, 0);
}
+ Py_DECREF(moduleName);
}
PyFile_WriteString(" in ", f);
PyFile_WriteObject(obj, f, 0);