mirror of
https://github.com/python/cpython.git
synced 2025-08-30 05:35:08 +00:00
GH-106895: Raise a ValueError
when attempting to disable events that cannot be disabled. (GH-107337)
This commit is contained in:
parent
d77d973335
commit
c6539b36c1
9 changed files with 120 additions and 52 deletions
|
@ -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};
|
||||
|
|
|
@ -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
|
||||
|
|
7
Python/executor_cases.c.h
generated
7
Python/executor_cases.c.h
generated
|
@ -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};
|
||||
|
|
7
Python/generated_cases.c.h
generated
7
Python/generated_cases.c.h
generated
|
@ -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};
|
||||
|
|
|
@ -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]*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue