summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorYury Selivanov <yselivanov@sprymix.com>2015-06-02 22:43:51 (GMT)
committerYury Selivanov <yselivanov@sprymix.com>2015-06-02 22:43:51 (GMT)
commitaab3c4a2110c3184ac0e9fc843fb1f3e07fbaf53 (patch)
tree25366f646da729ac7c4f351f5cbacc763b866ac6 /Python
parent231d90609b026dc709efd16d5bda610fbb12ebad (diff)
downloadcpython-aab3c4a2110c3184ac0e9fc843fb1f3e07fbaf53.zip
cpython-aab3c4a2110c3184ac0e9fc843fb1f3e07fbaf53.tar.gz
cpython-aab3c4a2110c3184ac0e9fc843fb1f3e07fbaf53.tar.bz2
Issue 24342: Let wrapper set by sys.set_coroutine_wrapper fail gracefully
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c39
-rw-r--r--Python/pystate.c1
2 files changed, 31 insertions, 9 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index bb2c0b9..2a1db17 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3921,7 +3921,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
if (co->co_flags & CO_GENERATOR) {
PyObject *gen;
- PyObject *coroutine_wrapper;
/* Don't need to keep the reference to f_back, it will be set
* when the generator is resumed. */
@@ -3935,14 +3934,9 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
if (gen == NULL)
return NULL;
- if (co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) {
- coroutine_wrapper = _PyEval_GetCoroutineWrapper();
- if (coroutine_wrapper != NULL) {
- PyObject *wrapped =
- PyObject_CallFunction(coroutine_wrapper, "N", gen);
- gen = wrapped;
- }
- }
+ if (co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))
+ return _PyEval_ApplyCoroutineWrapper(gen);
+
return gen;
}
@@ -4408,6 +4402,33 @@ _PyEval_GetCoroutineWrapper(void)
}
PyObject *
+_PyEval_ApplyCoroutineWrapper(PyObject *gen)
+{
+ PyObject *wrapped;
+ PyThreadState *tstate = PyThreadState_GET();
+ PyObject *wrapper = tstate->coroutine_wrapper;
+
+ if (tstate->in_coroutine_wrapper) {
+ assert(wrapper != NULL);
+ PyErr_Format(PyExc_RuntimeError,
+ "coroutine wrapper %.150R attempted "
+ "to recursively wrap %.150R",
+ wrapper,
+ gen);
+ return NULL;
+ }
+
+ if (wrapper == NULL) {
+ return gen;
+ }
+
+ tstate->in_coroutine_wrapper = 1;
+ wrapped = PyObject_CallFunction(wrapper, "N", gen);
+ tstate->in_coroutine_wrapper = 0;
+ return wrapped;
+}
+
+PyObject *
PyEval_GetBuiltins(void)
{
PyFrameObject *current_frame = PyEval_GetFrame();
diff --git a/Python/pystate.c b/Python/pystate.c
index 4ac05d6..7e0267a 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -213,6 +213,7 @@ new_threadstate(PyInterpreterState *interp, int init)
tstate->on_delete_data = NULL;
tstate->coroutine_wrapper = NULL;
+ tstate->in_coroutine_wrapper = 0;
if (init)
_PyThreadState_Init(tstate);