diff options
author | Mark Shannon <mark@hotpy.org> | 2017-10-22 21:41:51 (GMT) |
---|---|---|
committer | Antoine Pitrou <pitrou@free.fr> | 2017-10-22 21:41:51 (GMT) |
commit | ae3087c6382011c47db82fea4d05f8bbf514265d (patch) | |
tree | c5d832a760d9898700f1ca397a5a305734b3d77a /Include | |
parent | 91dc64ba3f51100540b2ab6c6cd72c3bb18a6d49 (diff) | |
download | cpython-ae3087c6382011c47db82fea4d05f8bbf514265d.zip cpython-ae3087c6382011c47db82fea4d05f8bbf514265d.tar.gz cpython-ae3087c6382011c47db82fea4d05f8bbf514265d.tar.bz2 |
Move exc state to generator. Fixes bpo-25612 (#1773)
Move exception state information from frame objects to coroutine (generator/thread) object where it belongs.
Diffstat (limited to 'Include')
-rw-r--r-- | Include/frameobject.h | 8 | ||||
-rw-r--r-- | Include/genobject.h | 3 | ||||
-rw-r--r-- | Include/pyerrors.h | 1 | ||||
-rw-r--r-- | Include/pystate.h | 27 |
4 files changed, 27 insertions, 12 deletions
diff --git a/Include/frameobject.h b/Include/frameobject.h index dbe0a84..a95baf8 100644 --- a/Include/frameobject.h +++ b/Include/frameobject.h @@ -30,14 +30,6 @@ typedef struct _frame { char f_trace_lines; /* Emit per-line trace events? */ char f_trace_opcodes; /* Emit per-opcode trace events? */ - /* In a generator, we need to be able to swap between the exception - state inside the generator and the exception state of the calling - frame (which shouldn't be impacted when the generator "yields" - from an except handler). - These three fields exist exactly for that, and are unused for - non-generator frames. See the save_exc_state and swap_exc_state - functions in ceval.c for details of their use. */ - PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; /* Borrowed reference to a generator, or NULL */ PyObject *f_gen; diff --git a/Include/genobject.h b/Include/genobject.h index b9db9f9..87fbe17 100644 --- a/Include/genobject.h +++ b/Include/genobject.h @@ -25,7 +25,8 @@ struct _frame; /* Avoid including frameobject.h */ /* Name of the generator. */ \ PyObject *prefix##_name; \ /* Qualified name of the generator. */ \ - PyObject *prefix##_qualname; + PyObject *prefix##_qualname; \ + _PyErr_StackItem prefix##_exc_state; typedef struct { /* The gi_ prefix is intended to remind of generator-iterator. */ diff --git a/Include/pyerrors.h b/Include/pyerrors.h index fcaba85..9418201 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -78,6 +78,7 @@ PyAPI_FUNC(void) PyErr_SetNone(PyObject *); PyAPI_FUNC(void) PyErr_SetObject(PyObject *, PyObject *); #ifndef Py_LIMITED_API PyAPI_FUNC(void) _PyErr_SetKeyError(PyObject *); +_PyErr_StackItem *_PyErr_GetTopmostException(PyThreadState *tstate); #endif PyAPI_FUNC(void) PyErr_SetString( PyObject *exception, diff --git a/Include/pystate.h b/Include/pystate.h index 507a598..238008f 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -123,6 +123,21 @@ typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *); #ifdef Py_LIMITED_API typedef struct _ts PyThreadState; #else + +typedef struct _err_stackitem { + /* This struct represents an entry on the exception stack, which is a + * per-coroutine state. (Coroutine in the computer science sense, + * including the thread and generators). + * This ensures that the exception state is not impacted by "yields" + * from an except handler. + */ + PyObject *exc_type, *exc_value, *exc_traceback; + + struct _err_stackitem *previous_item; + +} _PyErr_StackItem; + + typedef struct _ts { /* See Python/ceval.c for comments explaining most fields */ @@ -147,13 +162,19 @@ typedef struct _ts { PyObject *c_profileobj; PyObject *c_traceobj; + /* The exception currently being raised */ PyObject *curexc_type; PyObject *curexc_value; PyObject *curexc_traceback; - PyObject *exc_type; - PyObject *exc_value; - PyObject *exc_traceback; + /* The exception currently being handled, if no coroutines/generators + * are present. Always last element on the stack referred to be exc_info. + */ + _PyErr_StackItem exc_state; + + /* Pointer to the top of the stack of the exceptions currently + * being handled */ + _PyErr_StackItem *exc_info; PyObject *dict; /* Stores per-thread state */ |