summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2017-08-24 15:55:57 +0200
committerStefan Behnel <stefan_ml@behnel.de>2017-08-24 15:55:57 +0200
commit1299cdcb019e3f5b6dd88ee2bfafb8351161fe55 (patch)
tree3e520c0fe15af0508a42bb3454f4b909065d5d61
parent34b3dbf4eb312cd9cded345f681f104dae024dbe (diff)
downloadcython-1299cdcb019e3f5b6dd88ee2bfafb8351161fe55.tar.gz
Check frame back-pointer before we clear it. CPython can simply assert the identity in genobject.c because it always owns a frame itself for the current coroutine. Since Cython does not have frames here and uses the last frame of whatever traceback it currently owns, it's not clear if we can really give any guarantees better than best-effort here.
-rw-r--r--Cython/Utility/Coroutine.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index 016015d81..acc2166bb 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -400,16 +400,21 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/
__Pyx_Coroutine_ResetFrameBackpointer(self); \
(self)->exc_type = (self)->exc_value = (self)->exc_traceback = NULL; \
}
-static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineObject *self);
#if CYTHON_FAST_THREAD_STATE
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) \
__Pyx_PyGen__FetchStopIterationValue($local_tstate_cname, pvalue)
+#define __Pyx_Coroutine_ResetFrameBackpointer(self) \
+ __Pyx__Coroutine_ResetFrameBackpointer($local_tstate_cname, self)
#else
#define __Pyx_PyGen_FetchStopIterationValue(pvalue) \
__Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, pvalue)
+#define __Pyx_Coroutine_ResetFrameBackpointer(self) \
+ __Pyx__Coroutine_ResetFrameBackpointer(__Pyx_PyThreadState_Current, self)
#endif
static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *tstate, PyObject **pvalue); /*proto*/
+static CYTHON_INLINE void __Pyx__Coroutine_ResetFrameBackpointer(PyThreadState *tstate, __pyx_CoroutineObject *self);
+
//////////////////// Coroutine.proto ////////////////////
@@ -679,7 +684,7 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
return retval;
}
-static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineObject *self) {
+static CYTHON_INLINE void __Pyx__Coroutine_ResetFrameBackpointer(PyThreadState *tstate, __pyx_CoroutineObject *self) {
// Don't keep the reference to f_back any longer than necessary. It
// may keep a chain of frames alive or it could create a reference
// cycle.
@@ -689,7 +694,10 @@ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineO
#else
PyTracebackObject *tb = (PyTracebackObject *) self->exc_traceback;
PyFrameObject *f = tb->tb_frame;
- Py_CLEAR(f->f_back);
+ // do not accidentally break any other frame links
+ // FIXME: any other cases? e.g. do we need to follow up the back link chain?
+ if (f->f_back == tstate->frame)
+ Py_CLEAR(f->f_back);
#endif
}
}