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?
This commit is contained in:
Thomas Wouters 2006-04-15 23:27:28 +00:00
parent 81b092d0e6
commit b8f81d4863
3 changed files with 35 additions and 21 deletions

View File

@ -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()

View File

@ -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.
"""

View File

@ -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);