diff options
author | Mark Shannon <mark@hotpy.org> | 2021-03-24 17:56:12 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-24 17:56:12 (GMT) |
commit | 4958f5d69dd2bf86866c43491caf72f774ddec97 (patch) | |
tree | be5c90542cd132c43c2698c8b868c7ac9f8e95c2 | |
parent | 232f4cb6671f1ec5591faabbbbcc599da22781c4 (diff) | |
download | cpython-4958f5d69dd2bf86866c43491caf72f774ddec97.zip cpython-4958f5d69dd2bf86866c43491caf72f774ddec97.tar.gz cpython-4958f5d69dd2bf86866c43491caf72f774ddec97.tar.bz2 |
Only check evalbreaker after calls and on backwards egdes. Makes sure that __exit__ or __aexit__ is called in with statments in case of interrupt. (GH-18334)
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2020-02-03-13-23-10.bpo-29988.8_UB5w.rst | 3 | ||||
-rw-r--r-- | Python/ceval.c | 83 |
2 files changed, 40 insertions, 46 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-03-13-23-10.bpo-29988.8_UB5w.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-03-13-23-10.bpo-29988.8_UB5w.rst new file mode 100644 index 0000000..9a19c61 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-02-03-13-23-10.bpo-29988.8_UB5w.rst @@ -0,0 +1,3 @@ +Only handle asynchronous exceptions and requests to drop the GIL when +returning from a call or on the back edges of loops. Makes sure that +:meth:`__exit__` is always called in with statements, even for interrupts. diff --git a/Python/ceval.c b/Python/ceval.c index 3a37017..aef79e1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1331,7 +1331,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) TARGET_##op #ifdef LLTRACE -#define FAST_DISPATCH() \ +#define DISPATCH() \ { \ if (!lltrace && !_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ @@ -1341,7 +1341,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) goto fast_next_opcode; \ } #else -#define FAST_DISPATCH() \ +#define DISPATCH() \ { \ if (!_Py_TracingPossible(ceval2) && !PyDTrace_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ @@ -1352,20 +1352,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) } #endif -#define DISPATCH() \ - { \ - if (!_Py_atomic_load_relaxed(eval_breaker)) { \ - FAST_DISPATCH(); \ - } \ - continue; \ - } - #else #define TARGET(op) op -#define FAST_DISPATCH() goto fast_next_opcode -#define DISPATCH() continue +#define DISPATCH() goto fast_next_opcode + #endif +#define CHECK_EVAL_BREAKER() \ + if (_Py_atomic_load_relaxed(eval_breaker)) { \ + continue; \ + } + /* Tuple access macros */ @@ -1857,7 +1854,7 @@ main_loop: and that all operation that succeed call [FAST_]DISPATCH() ! */ case TARGET(NOP): { - FAST_DISPATCH(); + DISPATCH(); } case TARGET(LOAD_FAST): { @@ -1870,7 +1867,7 @@ main_loop: } Py_INCREF(value); PUSH(value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(LOAD_CONST): { @@ -1878,20 +1875,20 @@ main_loop: PyObject *value = GETITEM(consts, oparg); Py_INCREF(value); PUSH(value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(STORE_FAST): { PREDICTED(STORE_FAST); PyObject *value = POP(); SETLOCAL(oparg, value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(POP_TOP): { PyObject *value = POP(); Py_DECREF(value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(ROT_TWO): { @@ -1899,7 +1896,7 @@ main_loop: PyObject *second = SECOND(); SET_TOP(second); SET_SECOND(top); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(ROT_THREE): { @@ -1909,7 +1906,7 @@ main_loop: SET_TOP(second); SET_SECOND(third); SET_THIRD(top); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(ROT_FOUR): { @@ -1921,14 +1918,14 @@ main_loop: SET_SECOND(third); SET_THIRD(fourth); SET_FOURTH(top); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(DUP_TOP): { PyObject *top = TOP(); Py_INCREF(top); PUSH(top); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(DUP_TOP_TWO): { @@ -1939,7 +1936,7 @@ main_loop: STACK_GROW(2); SET_TOP(top); SET_SECOND(second); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(UNARY_POSITIVE): { @@ -2704,7 +2701,7 @@ main_loop: UNWIND_EXCEPT_HANDLER(b); Py_DECREF(POP()); JUMPBY(oparg); - FAST_DISPATCH(); + DISPATCH(); } else { PyObject *val = POP(); @@ -2718,7 +2715,7 @@ main_loop: PyObject *value = PyExc_AssertionError; Py_INCREF(value); PUSH(value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(LOAD_BUILD_CLASS): { @@ -3620,7 +3617,7 @@ main_loop: Py_DECREF(right); PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(CONTAINS_OP): { @@ -3637,7 +3634,7 @@ main_loop: PUSH(b); PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); - FAST_DISPATCH(); + DISPATCH(); } #define CANNOT_CATCH_MSG "catching classes that do not inherit from "\ @@ -3734,7 +3731,7 @@ main_loop: case TARGET(JUMP_FORWARD): { JUMPBY(oparg); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(POP_JUMP_IF_FALSE): { @@ -3743,12 +3740,12 @@ main_loop: int err; if (cond == Py_True) { Py_DECREF(cond); - FAST_DISPATCH(); + DISPATCH(); } if (cond == Py_False) { Py_DECREF(cond); JUMPTO(oparg); - FAST_DISPATCH(); + DISPATCH(); } err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -3767,12 +3764,12 @@ main_loop: int err; if (cond == Py_False) { Py_DECREF(cond); - FAST_DISPATCH(); + DISPATCH(); } if (cond == Py_True) { Py_DECREF(cond); JUMPTO(oparg); - FAST_DISPATCH(); + DISPATCH(); } err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -3792,11 +3789,11 @@ main_loop: if (cond == Py_True) { STACK_SHRINK(1); Py_DECREF(cond); - FAST_DISPATCH(); + DISPATCH(); } if (cond == Py_False) { JUMPTO(oparg); - FAST_DISPATCH(); + DISPATCH(); } err = PyObject_IsTrue(cond); if (err > 0) { @@ -3816,11 +3813,11 @@ main_loop: if (cond == Py_False) { STACK_SHRINK(1); Py_DECREF(cond); - FAST_DISPATCH(); + DISPATCH(); } if (cond == Py_True) { JUMPTO(oparg); - FAST_DISPATCH(); + DISPATCH(); } err = PyObject_IsTrue(cond); if (err > 0) { @@ -3838,18 +3835,8 @@ main_loop: case TARGET(JUMP_ABSOLUTE): { PREDICTED(JUMP_ABSOLUTE); JUMPTO(oparg); -#if FAST_LOOPS - /* Enabling this path speeds-up all while and for-loops by bypassing - the per-loop checks for signals. By default, this should be turned-off - because it prevents detection of a control-break in tight loops like - "while 1: pass". Compile with this option turned-on when you need - the speed-up and do not need break checking inside tight loops (ones - that contain only instructions ending with FAST_DISPATCH). - */ - FAST_DISPATCH(); -#else + CHECK_EVAL_BREAKER(); DISPATCH(); -#endif } case TARGET(GET_LEN): { @@ -4260,6 +4247,7 @@ main_loop: PUSH(res); if (res == NULL) goto error; + CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -4273,6 +4261,7 @@ main_loop: if (res == NULL) { goto error; } + CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -4292,6 +4281,7 @@ main_loop: if (res == NULL) { goto error; } + CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -4338,6 +4328,7 @@ main_loop: if (result == NULL) { goto error; } + CHECK_EVAL_BREAKER(); DISPATCH(); } |