summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2016-09-05 17:14:54 (GMT)
committerBenjamin Peterson <benjamin@python.org>2016-09-05 17:14:54 (GMT)
commit2f40ed4b94ad48cca01a96620da8c3eb15493539 (patch)
tree108449a0c9a2e4e918da13abbad61d1fcc4456ae
parentfb5ce7eea18b287679f4a8b70c2391f6e9d71833 (diff)
downloadcpython-2f40ed4b94ad48cca01a96620da8c3eb15493539.zip
cpython-2f40ed4b94ad48cca01a96620da8c3eb15493539.tar.gz
cpython-2f40ed4b94ad48cca01a96620da8c3eb15493539.tar.bz2
do not allow _PyGen_Finalize to fail (closes #27811)
Patch from Armin Rigo.
-rw-r--r--Lib/test/test_coroutines.py8
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/genobject.c25
3 files changed, 24 insertions, 12 deletions
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index d0cefb0..79cbec9 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -1565,6 +1565,14 @@ class CoroutineTest(unittest.TestCase):
finally:
aw.close()
+ def test_fatal_coro_warning(self):
+ # Issue 27811
+ async def func(): pass
+ with warnings.catch_warnings():
+ warnings.filterwarnings("error")
+ func()
+ support.gc_collect()
+
class CoroAsyncIOCompatTest(unittest.TestCase):
diff --git a/Misc/NEWS b/Misc/NEWS
index 90f0bdd..8558db4 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: TBA
Core and Builtins
-----------------
+- Issue #27811: Fix a crash when a coroutine that has not been awaited is
+ finalized with warnings-as-errors enabled.
+
- Issue #27587: Fix another issue found by PVS-Studio: Null pointer check
after use of 'def' in _PyState_AddModule().
Initial patch by Christian Heimes.
diff --git a/Objects/genobject.c b/Objects/genobject.c
index b3e0a46..a9ea5c2 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -24,26 +24,27 @@ _PyGen_Finalize(PyObject *self)
PyObject *res;
PyObject *error_type, *error_value, *error_traceback;
+ if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
+ /* Generator isn't paused, so no need to close */
+ return;
+
+ /* Save the current exception, if any. */
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+
/* If `gen` is a coroutine, and if it was never awaited on,
issue a RuntimeWarning. */
if (gen->gi_code != NULL
&& ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE
- && gen->gi_frame != NULL
&& gen->gi_frame->f_lasti == -1
&& !PyErr_Occurred()
&& PyErr_WarnFormat(PyExc_RuntimeWarning, 1,
"coroutine '%.50S' was never awaited",
- gen->gi_qualname))
- return;
-
- if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
- /* Generator isn't paused, so no need to close */
- return;
-
- /* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- res = gen_close(gen, NULL);
+ gen->gi_qualname)) {
+ res = NULL; /* oops, exception */
+ }
+ else {
+ res = gen_close(gen, NULL);
+ }
if (res == NULL)
PyErr_WriteUnraisable(self);