Commit b6ed2725 authored by Stefan Behnel's avatar Stefan Behnel

Always break the frame back-pointer chain when exiting from a generator, so...

Always break the frame back-pointer chain when exiting from a generator, so that it can be reconnected on the next entry.
parent c810d343
...@@ -409,12 +409,12 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/ ...@@ -409,12 +409,12 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/
// macros for exception state swapping instead of inline functions to make use of the local thread state context // macros for exception state swapping instead of inline functions to make use of the local thread state context
#if CYTHON_USE_EXC_INFO_STACK #if CYTHON_USE_EXC_INFO_STACK
#define __Pyx_Coroutine_SwapException(self) __Pyx_Coroutine_ResetFrameBackpointer(self) #define __Pyx_Coroutine_SwapException(self)
#define __Pyx_Coroutine_ResetAndClearException(self) __Pyx_Coroutine_ExceptionClear(&(self)->gi_exc_state) #define __Pyx_Coroutine_ResetAndClearException(self) __Pyx_Coroutine_ExceptionClear(&(self)->gi_exc_state)
#else #else
#define __Pyx_Coroutine_SwapException(self) { \ #define __Pyx_Coroutine_SwapException(self) { \
__Pyx_ExceptionSwap(&(self)->gi_exc_state.exc_type, &(self)->gi_exc_state.exc_value, &(self)->gi_exc_state.exc_traceback); \ __Pyx_ExceptionSwap(&(self)->gi_exc_state.exc_type, &(self)->gi_exc_state.exc_value, &(self)->gi_exc_state.exc_traceback); \
__Pyx_Coroutine_ResetFrameBackpointer(self); \ __Pyx_Coroutine_ResetFrameBackpointer(&(self)->gi_exc_state); \
} }
#define __Pyx_Coroutine_ResetAndClearException(self) { \ #define __Pyx_Coroutine_ResetAndClearException(self) { \
__Pyx_ExceptionReset((self)->gi_exc_state.exc_type, (self)->gi_exc_state.exc_value, (self)->gi_exc_state.exc_traceback); \ __Pyx_ExceptionReset((self)->gi_exc_state.exc_type, (self)->gi_exc_state.exc_value, (self)->gi_exc_state.exc_traceback); \
...@@ -430,7 +430,7 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/ ...@@ -430,7 +430,7 @@ static PyObject *__Pyx_Coroutine_Throw(PyObject *gen, PyObject *args); /*proto*/
__Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, pvalue) __Pyx_PyGen__FetchStopIterationValue(__Pyx_PyThreadState_Current, pvalue)
#endif #endif
static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *tstate, PyObject **pvalue); /*proto*/ static int __Pyx_PyGen__FetchStopIterationValue(PyThreadState *tstate, PyObject **pvalue); /*proto*/
static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineObject *self); /*proto*/ static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state); /*proto*/
//////////////////// Coroutine.proto //////////////////// //////////////////// Coroutine.proto ////////////////////
...@@ -746,22 +746,24 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i ...@@ -746,22 +746,24 @@ PyObject *__Pyx_Coroutine_SendEx(__pyx_CoroutineObject *self, PyObject *value, i
exc_state = &self->gi_exc_state; exc_state = &self->gi_exc_state;
tstate->exc_info = exc_state->previous_item; tstate->exc_info = exc_state->previous_item;
exc_state->previous_item = NULL; exc_state->previous_item = NULL;
// Cut off the exception frame chain so that we can reconnect it on re-entry above.
__Pyx_Coroutine_ResetFrameBackpointer(exc_state);
#endif #endif
return retval; return retval;
} }
static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__pyx_CoroutineObject *self) { static CYTHON_INLINE void __Pyx_Coroutine_ResetFrameBackpointer(__Pyx_ExcInfoStruct *exc_state) {
// Don't keep the reference to f_back any longer than necessary. It // 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 // may keep a chain of frames alive or it could create a reference
// cycle. // cycle.
PyObject *tb = self->gi_exc_state.exc_traceback; PyObject *exc_tb = exc_state->exc_traceback;
if (likely(tb)) { if (likely(exc_tb)) {
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON #if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
// FIXME: what to do in PyPy? // FIXME: what to do in PyPy?
#else #else
PyTracebackObject *tb = (PyTracebackObject *) tb; PyTracebackObject *tb = (PyTracebackObject *) exc_tb;
PyFrameObject *f = tb->tb_frame; PyFrameObject *f = tb->tb_frame;
Py_CLEAR(f->f_back); Py_CLEAR(f->f_back);
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment