]> granicus.if.org Git - python/commitdiff
do not allow _PyGen_Finalize to fail (closes #27811)
authorBenjamin Peterson <benjamin@python.org>
Mon, 5 Sep 2016 17:14:54 +0000 (10:14 -0700)
committerBenjamin Peterson <benjamin@python.org>
Mon, 5 Sep 2016 17:14:54 +0000 (10:14 -0700)
Patch from Armin Rigo.

Lib/test/test_coroutines.py
Misc/NEWS
Objects/genobject.c

index d0cefb0ef4434b4a98c9ec6c53660f369f8fd3bb..79cbec9899b0855ce3eda82f21d4ec14a1eaf479 100644 (file)
@@ -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):
 
index 90f0bddaf8e3bfd17cf6355f71c29cfc0e388583..8558db4df378da9c7617f2c57e662011984016db 100644 (file)
--- 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.
index b3e0a46e8b3581f26d7466f8b7a626cfcfa7d1ac..a9ea5c24786974b93ac22183f00963836fb99ef4 100644 (file)
@@ -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);