Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Kirill Smelkov
cpython
Commits
a370fcf3
Commit
a370fcf3
authored
13 years ago
by
Antoine Pitrou
Browse files
Options
Download
Email Patches
Plain Diff
Issue #12791: Break reference cycles early when a generator exits with an exception.
parent
0c17d0d9
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
76 additions
and
0 deletions
+76
-0
Lib/test/test_exceptions.py
Lib/test/test_exceptions.py
+62
-0
Misc/NEWS
Misc/NEWS
+3
-0
Objects/genobject.c
Objects/genobject.c
+11
-0
No files found.
Lib/test/test_exceptions.py
View file @
a370fcf3
...
...
@@ -607,6 +607,68 @@ class ExceptionTests(unittest.TestCase):
gc_collect
()
self
.
assertEqual
(
sys
.
exc_info
(),
(
None
,
None
,
None
))
def
_check_generator_cleanup_exc_state
(
self
,
testfunc
):
# Issue #12791: exception state is cleaned up as soon as a generator
# is closed (reference cycles are broken).
class
MyException
(
Exception
):
def
__init__
(
self
,
obj
):
self
.
obj
=
obj
class
MyObj
:
pass
def
raising_gen
():
try
:
raise
MyException
(
obj
)
except
MyException
:
yield
obj
=
MyObj
()
wr
=
weakref
.
ref
(
obj
)
g
=
raising_gen
()
next
(
g
)
testfunc
(
g
)
g
=
obj
=
None
obj
=
wr
()
self
.
assertIs
(
obj
,
None
)
def
test_generator_throw_cleanup_exc_state
(
self
):
def
do_throw
(
g
):
try
:
g
.
throw
(
RuntimeError
())
except
RuntimeError
:
pass
self
.
_check_generator_cleanup_exc_state
(
do_throw
)
def
test_generator_close_cleanup_exc_state
(
self
):
def
do_close
(
g
):
g
.
close
()
self
.
_check_generator_cleanup_exc_state
(
do_close
)
def
test_generator_del_cleanup_exc_state
(
self
):
def
do_del
(
g
):
g
=
None
self
.
_check_generator_cleanup_exc_state
(
do_del
)
def
test_generator_next_cleanup_exc_state
(
self
):
def
do_next
(
g
):
try
:
next
(
g
)
except
StopIteration
:
pass
else
:
self
.
fail
(
"should have raised StopIteration"
)
self
.
_check_generator_cleanup_exc_state
(
do_next
)
def
test_generator_send_cleanup_exc_state
(
self
):
def
do_send
(
g
):
try
:
g
.
send
(
None
)
except
StopIteration
:
pass
else
:
self
.
fail
(
"should have raised StopIteration"
)
self
.
_check_generator_cleanup_exc_state
(
do_send
)
def
test_3114
(
self
):
# Bug #3114: in its destructor, MyObject retrieves a pointer to
# obsolete and/or deallocated objects.
...
...
This diff is collapsed.
Click to expand it.
Misc/NEWS
View file @
a370fcf3
...
...
@@ -10,6 +10,9 @@ What's New in Python 3.2.3?
Core and Builtins
-----------------
- Issue #12791: Break reference cycles early when a generator exits with
an exception.
- Issue #12266: Fix str.capitalize() to correctly uppercase/lowercase
titlecased and cased non-letter characters.
...
...
This diff is collapsed.
Click to expand it.
Objects/genobject.c
View file @
a370fcf3
...
...
@@ -100,6 +100,17 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
if
(
!
result
||
f
->
f_stacktop
==
NULL
)
{
/* generator can't be rerun, so release the frame */
/* first clean reference cycle through stored exception traceback */
PyObject
*
t
,
*
v
,
*
tb
;
t
=
f
->
f_exc_type
;
v
=
f
->
f_exc_value
;
tb
=
f
->
f_exc_traceback
;
f
->
f_exc_type
=
NULL
;
f
->
f_exc_value
=
NULL
;
f
->
f_exc_traceback
=
NULL
;
Py_XDECREF
(
t
);
Py_XDECREF
(
v
);
Py_XDECREF
(
tb
);
Py_DECREF
(
f
);
gen
->
gi_frame
=
NULL
;
}
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment