diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2017-08-24 15:55:57 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2017-08-24 15:55:57 +0200 |
commit | 1299cdcb019e3f5b6dd88ee2bfafb8351161fe55 (patch) | |
tree | 3e520c0fe15af0508a42bb3454f4b909065d5d61 | |
parent | 34b3dbf4eb312cd9cded345f681f104dae024dbe (diff) | |
download | cython-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.c | 14 |
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 } } |