diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/bytecodes.c | 7 | ||||
-rw-r--r-- | Python/ceval.c | 13 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 7 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 7 | ||||
-rw-r--r-- | Python/instrumentation.c | 79 |
5 files changed, 63 insertions, 50 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c index da9d8e2..2b871e8 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2672,7 +2672,12 @@ dummy_func( assert(val && PyExceptionInstance_Check(val)); exc = PyExceptionInstance_Class(val); tb = PyException_GetTraceback(val); - Py_XDECREF(tb); + if (tb == NULL) { + tb = Py_None; + } + else { + Py_DECREF(tb); + } assert(PyLong_Check(lasti)); (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[4] = {NULL, exc, val, tb}; diff --git a/Python/ceval.c b/Python/ceval.c index a5d37c0..c0b37b3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -193,7 +193,7 @@ static int monitor_stop_iteration(PyThreadState *tstate, static void monitor_unwind(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr); -static void monitor_handled(PyThreadState *tstate, +static int monitor_handled(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *exc); static void monitor_throw(PyThreadState *tstate, @@ -886,7 +886,9 @@ exception_unwind: PyObject *exc = _PyErr_GetRaisedException(tstate); PUSH(exc); JUMPTO(handler); - monitor_handled(tstate, frame, next_instr, exc); + if (monitor_handled(tstate, frame, next_instr, exc) < 0) { + goto exception_unwind; + } /* Resume normal execution */ DISPATCH(); } @@ -1924,6 +1926,7 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame, PyErr_SetRaisedException(exc); } else { + assert(PyErr_Occurred()); Py_DECREF(exc); } return err; @@ -1988,15 +1991,15 @@ monitor_unwind(PyThreadState *tstate, } -static void +static int monitor_handled(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *instr, PyObject *exc) { if (no_tools_for_event(tstate, frame, PY_MONITORING_EVENT_EXCEPTION_HANDLED)) { - return; + return 0; } - _Py_call_instrumentation_arg(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED, frame, instr, exc); + return _Py_call_instrumentation_arg(tstate, PY_MONITORING_EVENT_EXCEPTION_HANDLED, frame, instr, exc); } static void diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 0f04b42..f3e24bc 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -1949,7 +1949,12 @@ assert(val && PyExceptionInstance_Check(val)); exc = PyExceptionInstance_Class(val); tb = PyException_GetTraceback(val); - Py_XDECREF(tb); + if (tb == NULL) { + tb = Py_None; + } + else { + Py_DECREF(tb); + } assert(PyLong_Check(lasti)); (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[4] = {NULL, exc, val, tb}; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 37ffb56..6ac622b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3315,7 +3315,12 @@ assert(val && PyExceptionInstance_Check(val)); exc = PyExceptionInstance_Class(val); tb = PyException_GetTraceback(val); - Py_XDECREF(tb); + if (tb == NULL) { + tb = Py_None; + } + else { + Py_DECREF(tb); + } assert(PyLong_Check(lasti)); (void)lasti; // Shut up compiler warning if asserts are off PyObject *stack[4] = {NULL, exc, val, tb}; diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 280e13d..123c20d 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -702,29 +702,13 @@ instrument_per_instruction(PyCodeObject *code, int i) *opcode_ptr = INSTRUMENTED_INSTRUCTION; } -#ifndef NDEBUG -static bool -instruction_has_event(PyCodeObject *code, int offset) -{ - _Py_CODEUNIT instr = _PyCode_CODE(code)[offset]; - int opcode = instr.op.code; - if (opcode == INSTRUMENTED_LINE) { - opcode = code->_co_monitoring->lines[offset].original_opcode; - } - if (opcode == INSTRUMENTED_INSTRUCTION) { - opcode = code->_co_monitoring->per_instruction_opcodes[offset]; - } - return opcode_has_event(opcode); -} -#endif - static void remove_tools(PyCodeObject * code, int offset, int event, int tools) { assert(event != PY_MONITORING_EVENT_LINE); assert(event != PY_MONITORING_EVENT_INSTRUCTION); - assert(event < PY_MONITORING_INSTRUMENTED_EVENTS); - assert(instruction_has_event(code, offset)); + assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); + assert(opcode_has_event(_Py_GetBaseOpcode(code, offset))); _PyCoMonitoringData *monitoring = code->_co_monitoring; if (monitoring && monitoring->tools) { monitoring->tools[offset] &= ~tools; @@ -779,7 +763,7 @@ add_tools(PyCodeObject * code, int offset, int event, int tools) { assert(event != PY_MONITORING_EVENT_LINE); assert(event != PY_MONITORING_EVENT_INSTRUCTION); - assert(event < PY_MONITORING_INSTRUMENTED_EVENTS); + assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); assert(code->_co_monitoring); if (code->_co_monitoring && code->_co_monitoring->tools @@ -919,7 +903,7 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, event == PY_MONITORING_EVENT_C_RETURN); event = PY_MONITORING_EVENT_CALL; } - if (event < PY_MONITORING_INSTRUMENTED_EVENTS) { + if (PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { CHECK(is_version_up_to_date(code, interp)); CHECK(instrumentation_cross_checks(interp, code)); if (code->_co_monitoring->tools) { @@ -940,6 +924,26 @@ get_tools_for_instruction(PyCodeObject *code, PyInterpreterState *interp, int i, return tools; } +static const char *const event_names [] = { + [PY_MONITORING_EVENT_PY_START] = "PY_START", + [PY_MONITORING_EVENT_PY_RESUME] = "PY_RESUME", + [PY_MONITORING_EVENT_PY_RETURN] = "PY_RETURN", + [PY_MONITORING_EVENT_PY_YIELD] = "PY_YIELD", + [PY_MONITORING_EVENT_CALL] = "CALL", + [PY_MONITORING_EVENT_LINE] = "LINE", + [PY_MONITORING_EVENT_INSTRUCTION] = "INSTRUCTION", + [PY_MONITORING_EVENT_JUMP] = "JUMP", + [PY_MONITORING_EVENT_BRANCH] = "BRANCH", + [PY_MONITORING_EVENT_C_RETURN] = "C_RETURN", + [PY_MONITORING_EVENT_PY_THROW] = "PY_THROW", + [PY_MONITORING_EVENT_RAISE] = "RAISE", + [PY_MONITORING_EVENT_RERAISE] = "RERAISE", + [PY_MONITORING_EVENT_EXCEPTION_HANDLED] = "EXCEPTION_HANDLED", + [PY_MONITORING_EVENT_C_RAISE] = "C_RAISE", + [PY_MONITORING_EVENT_PY_UNWIND] = "PY_UNWIND", + [PY_MONITORING_EVENT_STOP_ITERATION] = "STOP_ITERATION", +}; + static int call_instrumentation_vector( PyThreadState *tstate, int event, @@ -984,7 +988,18 @@ call_instrumentation_vector( } else { /* DISABLE */ - remove_tools(code, offset, event, 1 << tool); + if (!PY_MONITORING_IS_INSTRUMENTED_EVENT(event)) { + PyErr_Format(PyExc_ValueError, + "Cannot disable %s events. Callback removed.", + event_names[event]); + /* Clear tool to prevent infinite loop */ + Py_CLEAR(interp->monitoring_callables[tool][event]); + err = -1; + break; + } + else { + remove_tools(code, offset, event, 1 << tool); + } } } Py_DECREF(offset_obj); @@ -1262,7 +1277,7 @@ initialize_tools(PyCodeObject *code) assert(event > 0); } assert(event >= 0); - assert(event < PY_MONITORING_INSTRUMENTED_EVENTS); + assert(PY_MONITORING_IS_INSTRUMENTED_EVENT(event)); tools[i] = code->_co_monitoring->active_monitors.tools[event]; CHECK(tools[i] != 0); } @@ -2017,26 +2032,6 @@ add_power2_constant(PyObject *obj, const char *name, int i) return err; } -static const char *const event_names [] = { - [PY_MONITORING_EVENT_PY_START] = "PY_START", - [PY_MONITORING_EVENT_PY_RESUME] = "PY_RESUME", - [PY_MONITORING_EVENT_PY_RETURN] = "PY_RETURN", - [PY_MONITORING_EVENT_PY_YIELD] = "PY_YIELD", - [PY_MONITORING_EVENT_CALL] = "CALL", - [PY_MONITORING_EVENT_LINE] = "LINE", - [PY_MONITORING_EVENT_INSTRUCTION] = "INSTRUCTION", - [PY_MONITORING_EVENT_JUMP] = "JUMP", - [PY_MONITORING_EVENT_BRANCH] = "BRANCH", - [PY_MONITORING_EVENT_C_RETURN] = "C_RETURN", - [PY_MONITORING_EVENT_PY_THROW] = "PY_THROW", - [PY_MONITORING_EVENT_RAISE] = "RAISE", - [PY_MONITORING_EVENT_RERAISE] = "RERAISE", - [PY_MONITORING_EVENT_EXCEPTION_HANDLED] = "EXCEPTION_HANDLED", - [PY_MONITORING_EVENT_C_RAISE] = "C_RAISE", - [PY_MONITORING_EVENT_PY_UNWIND] = "PY_UNWIND", - [PY_MONITORING_EVENT_STOP_ITERATION] = "STOP_ITERATION", -}; - /*[clinic input] monitoring._all_events [clinic start generated code]*/ |