summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2017-10-22 21:41:51 (GMT)
committerAntoine Pitrou <pitrou@free.fr>2017-10-22 21:41:51 (GMT)
commitae3087c6382011c47db82fea4d05f8bbf514265d (patch)
treec5d832a760d9898700f1ca397a5a305734b3d77a /Include
parent91dc64ba3f51100540b2ab6c6cd72c3bb18a6d49 (diff)
downloadcpython-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.h8
-rw-r--r--Include/genobject.h3
-rw-r--r--Include/pyerrors.h1
-rw-r--r--Include/pystate.h27
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 */