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 00000000000..9a19c615a88 --- /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 892d668816a..de86184635a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -837,7 +837,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) TARGET_##op #ifdef LLTRACE -#define FAST_DISPATCH() \ +#define DISPATCH() \ { \ if (!lltrace && !_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ @@ -847,7 +847,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) goto fast_next_opcode; \ } #else -#define FAST_DISPATCH() \ +#define DISPATCH() \ { \ if (!_Py_TracingPossible(ceval) && !PyDTrace_LINE_ENABLED()) { \ f->f_lasti = INSTR_OFFSET(); \ @@ -858,20 +858,17 @@ _PyEval_EvalFrameDefault(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 */ @@ -1323,7 +1320,7 @@ main_loop: and that all operation that succeed call [FAST_]DISPATCH() ! */ case TARGET(NOP): { - FAST_DISPATCH(); + DISPATCH(); } case TARGET(LOAD_FAST): { @@ -1336,7 +1333,7 @@ main_loop: } Py_INCREF(value); PUSH(value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(LOAD_CONST): { @@ -1344,20 +1341,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): { @@ -1365,7 +1362,7 @@ main_loop: PyObject *second = SECOND(); SET_TOP(second); SET_SECOND(top); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(ROT_THREE): { @@ -1375,7 +1372,7 @@ main_loop: SET_TOP(second); SET_SECOND(third); SET_THIRD(top); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(ROT_FOUR): { @@ -1387,14 +1384,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): { @@ -1405,7 +1402,7 @@ main_loop: STACK_GROW(2); SET_TOP(top); SET_SECOND(second); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(UNARY_POSITIVE): { @@ -2147,7 +2144,7 @@ main_loop: UNWIND_EXCEPT_HANDLER(b); Py_DECREF(POP()); JUMPBY(oparg); - FAST_DISPATCH(); + DISPATCH(); } else { PyObject *val = POP(); @@ -2161,7 +2158,7 @@ main_loop: PyObject *value = PyExc_AssertionError; Py_INCREF(value); PUSH(value); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(LOAD_BUILD_CLASS): { @@ -2880,7 +2877,7 @@ main_loop: Py_DECREF(right); PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(CONTAINS_OP): { @@ -2897,7 +2894,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 "\ @@ -2994,7 +2991,7 @@ main_loop: case TARGET(JUMP_FORWARD): { JUMPBY(oparg); - FAST_DISPATCH(); + DISPATCH(); } case TARGET(POP_JUMP_IF_FALSE): { @@ -3003,12 +3000,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); @@ -3027,12 +3024,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); @@ -3052,11 +3049,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) { @@ -3076,11 +3073,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) { @@ -3098,18 +3095,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_ITER): { @@ -3363,6 +3350,7 @@ main_loop: PUSH(res); if (res == NULL) goto error; + CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -3376,6 +3364,7 @@ main_loop: if (res == NULL) { goto error; } + CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -3395,6 +3384,7 @@ main_loop: if (res == NULL) { goto error; } + CHECK_EVAL_BREAKER(); DISPATCH(); } @@ -3441,6 +3431,7 @@ main_loop: if (result == NULL) { goto error; } + CHECK_EVAL_BREAKER(); DISPATCH(); }