diff options
author | Mark Shannon <mark@hotpy.org> | 2023-07-28 09:53:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-28 09:53:33 (GMT) |
commit | 0902afbae29ef88bf9d212a7e11f9f17b6cbdeb5 (patch) | |
tree | eeada04f808fc41bfeb35fb8ac87dd3297c9a037 | |
parent | 3b1a4c18426c78a2fda0d59728bfe9eb92889722 (diff) | |
download | cpython-0902afbae29ef88bf9d212a7e11f9f17b6cbdeb5.zip cpython-0902afbae29ef88bf9d212a7e11f9f17b6cbdeb5.tar.gz cpython-0902afbae29ef88bf9d212a7e11f9f17b6cbdeb5.tar.bz2 |
[3.12] GH-106895: Raise a `ValueError` when attempting to disable events that cannot be disabled. (GH-107337) (GH-107351)
-rw-r--r-- | Include/internal/pycore_instruments.h | 3 | ||||
-rw-r--r-- | Lib/test/test_monitoring.py | 52 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst | 2 | ||||
-rw-r--r-- | Objects/classobject.c | 2 | ||||
-rw-r--r-- | Python/bytecodes.c | 7 | ||||
-rw-r--r-- | Python/ceval.c | 13 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 193 | ||||
-rw-r--r-- | Python/instrumentation.c | 79 |
8 files changed, 207 insertions, 144 deletions
diff --git a/Include/internal/pycore_instruments.h b/Include/internal/pycore_instruments.h index cfa5d09..ccccd54 100644 --- a/Include/internal/pycore_instruments.h +++ b/Include/internal/pycore_instruments.h @@ -28,7 +28,8 @@ extern "C" { #define PY_MONITORING_EVENT_BRANCH 8 #define PY_MONITORING_EVENT_STOP_ITERATION 9 -#define PY_MONITORING_INSTRUMENTED_EVENTS 10 +#define PY_MONITORING_IS_INSTRUMENTED_EVENT(ev) \ + ((ev) <= PY_MONITORING_EVENT_STOP_ITERATION) /* Other events, mainly exceptions */ diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 8bf95a7..9685a43 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -136,20 +136,27 @@ class MonitoringCountTest(MonitoringTestBase, unittest.TestCase): E = sys.monitoring.events -SIMPLE_EVENTS = [ +INSTRUMENTED_EVENTS = [ (E.PY_START, "start"), (E.PY_RESUME, "resume"), (E.PY_RETURN, "return"), (E.PY_YIELD, "yield"), (E.JUMP, "jump"), (E.BRANCH, "branch"), +] + +EXCEPT_EVENTS = [ (E.RAISE, "raise"), (E.PY_UNWIND, "unwind"), (E.EXCEPTION_HANDLED, "exception_handled"), +] + +SIMPLE_EVENTS = INSTRUMENTED_EVENTS + EXCEPT_EVENTS + [ (E.C_RAISE, "c_raise"), (E.C_RETURN, "c_return"), ] + SIMPLE_EVENT_SET = functools.reduce(operator.or_, [ev for (ev, _) in SIMPLE_EVENTS], 0) | E.CALL @@ -618,6 +625,49 @@ class LineMonitoringTest(MonitoringTestBase, unittest.TestCase): self.check_lines(func2, [1,2,3,4,5,6]) +class TestDisable(MonitoringTestBase, unittest.TestCase): + + def gen(self, cond): + for i in range(10): + if cond: + yield 1 + else: + yield 2 + + def raise_handle_reraise(self): + try: + 1/0 + except: + raise + + def test_disable_legal_events(self): + for event, name in INSTRUMENTED_EVENTS: + try: + counter = CounterWithDisable() + counter.disable = True + sys.monitoring.register_callback(TEST_TOOL, event, counter) + sys.monitoring.set_events(TEST_TOOL, event) + for _ in self.gen(1): + pass + self.assertLess(counter.count, 4) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) + sys.monitoring.register_callback(TEST_TOOL, event, None) + + + def test_disable_illegal_events(self): + for event, name in EXCEPT_EVENTS: + try: + counter = CounterWithDisable() + counter.disable = True + sys.monitoring.register_callback(TEST_TOOL, event, counter) + sys.monitoring.set_events(TEST_TOOL, event) + with self.assertRaises(ValueError): + self.raise_handle_reraise() + finally: + sys.monitoring.set_events(TEST_TOOL, 0) + sys.monitoring.register_callback(TEST_TOOL, event, None) + class ExceptionRecorder: diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst new file mode 100644 index 0000000..370a29d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst @@ -0,0 +1,2 @@ +Raise a ``ValueError`` when a monitoring callback funtion returns +``DISABLE`` for events that cannot be disabled locally. diff --git a/Objects/classobject.c b/Objects/classobject.c index 71c4a4e..12dc276 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -48,6 +48,7 @@ method_vectorcall(PyObject *method, PyObject *const *args, PyObject *self = PyMethod_GET_SELF(method); PyObject *func = PyMethod_GET_FUNCTION(method); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + assert(nargs == 0 || args[nargs-1]); PyObject *result; if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) { @@ -56,6 +57,7 @@ method_vectorcall(PyObject *method, PyObject *const *args, nargs += 1; PyObject *tmp = newargs[0]; newargs[0] = self; + assert(newargs[nargs-1]); result = _PyObject_VectorcallTstate(tstate, func, newargs, nargs, kwnames); newargs[0] = tmp; diff --git a/Python/bytecodes.c b/Python/bytecodes.c index adfa5ce..7ee48c7 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2476,7 +2476,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 899f135..27dea27 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -194,7 +194,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, @@ -969,7 +969,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(); } @@ -2007,6 +2009,7 @@ do_monitor_exc(PyThreadState *tstate, _PyInterpreterFrame *frame, PyErr_SetRaisedException(exc); } else { + assert(PyErr_Occurred()); Py_DECREF(exc); } return err; @@ -2071,15 +2074,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/generated_cases.c.h b/Python/generated_cases.c.h index d5c048a..eabb9fe 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -3579,14 +3579,19 @@ 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}; res = PyObject_Vectorcall(exit_func, stack + 1, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); if (res == NULL) goto error; - #line 3590 "Python/generated_cases.c.h" + #line 3595 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = res; DISPATCH(); @@ -3595,7 +3600,7 @@ TARGET(PUSH_EXC_INFO) { PyObject *new_exc = stack_pointer[-1]; PyObject *prev_exc; - #line 2489 "Python/bytecodes.c" + #line 2494 "Python/bytecodes.c" _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { prev_exc = exc_info->exc_value; @@ -3605,7 +3610,7 @@ } assert(PyExceptionInstance_Check(new_exc)); exc_info->exc_value = Py_NewRef(new_exc); - #line 3609 "Python/generated_cases.c.h" + #line 3614 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = new_exc; stack_pointer[-2] = prev_exc; @@ -3619,7 +3624,7 @@ uint32_t type_version = read_u32(&next_instr[1].cache); uint32_t keys_version = read_u32(&next_instr[3].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2501 "Python/bytecodes.c" + #line 2506 "Python/bytecodes.c" /* Cached method object */ PyTypeObject *self_cls = Py_TYPE(self); assert(type_version != 0); @@ -3636,7 +3641,7 @@ assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); res = self; assert(oparg & 1); - #line 3640 "Python/generated_cases.c.h" + #line 3645 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -3650,7 +3655,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2520 "Python/bytecodes.c" + #line 2525 "Python/bytecodes.c" PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); @@ -3660,7 +3665,7 @@ res2 = Py_NewRef(descr); res = self; assert(oparg & 1); - #line 3664 "Python/generated_cases.c.h" + #line 3669 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -3674,7 +3679,7 @@ PyObject *res; uint32_t type_version = read_u32(&next_instr[1].cache); PyObject *descr = read_obj(&next_instr[5].cache); - #line 2532 "Python/bytecodes.c" + #line 2537 "Python/bytecodes.c" PyTypeObject *self_cls = Py_TYPE(self); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; @@ -3688,7 +3693,7 @@ res2 = Py_NewRef(descr); res = self; assert(oparg & 1); - #line 3692 "Python/generated_cases.c.h" + #line 3697 "Python/generated_cases.c.h" STACK_GROW(((oparg & 1) ? 1 : 0)); stack_pointer[-1] = res; if (oparg & 1) { stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))] = res2; } @@ -3697,16 +3702,16 @@ } TARGET(KW_NAMES) { - #line 2548 "Python/bytecodes.c" + #line 2553 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg < PyTuple_GET_SIZE(frame->f_code->co_consts)); kwnames = GETITEM(frame->f_code->co_consts, oparg); - #line 3705 "Python/generated_cases.c.h" + #line 3710 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_CALL) { - #line 2554 "Python/bytecodes.c" + #line 2559 "Python/bytecodes.c" int is_meth = PEEK(oparg+2) != NULL; int total_args = oparg + is_meth; PyObject *function = PEEK(total_args + 1); @@ -3719,7 +3724,7 @@ _PyCallCache *cache = (_PyCallCache *)next_instr; INCREMENT_ADAPTIVE_COUNTER(cache->counter); GO_TO_INSTRUCTION(CALL); - #line 3723 "Python/generated_cases.c.h" + #line 3728 "Python/generated_cases.c.h" } TARGET(CALL) { @@ -3729,7 +3734,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2599 "Python/bytecodes.c" + #line 2604 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -3811,7 +3816,7 @@ Py_DECREF(args[i]); } if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3815 "Python/generated_cases.c.h" + #line 3820 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3823,7 +3828,7 @@ TARGET(CALL_BOUND_METHOD_EXACT_ARGS) { PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; - #line 2687 "Python/bytecodes.c" + #line 2692 "Python/bytecodes.c" DEOPT_IF(method != NULL, CALL); DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL); STAT_INC(CALL, hit); @@ -3833,7 +3838,7 @@ PEEK(oparg + 2) = Py_NewRef(meth); // method Py_DECREF(callable); GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS); - #line 3837 "Python/generated_cases.c.h" + #line 3842 "Python/generated_cases.c.h" } TARGET(CALL_PY_EXACT_ARGS) { @@ -3842,7 +3847,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; uint32_t func_version = read_u32(&next_instr[1].cache); - #line 2699 "Python/bytecodes.c" + #line 2704 "Python/bytecodes.c" assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); int is_meth = method != NULL; @@ -3868,7 +3873,7 @@ JUMPBY(INLINE_CACHE_ENTRIES_CALL); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 3872 "Python/generated_cases.c.h" + #line 3877 "Python/generated_cases.c.h" } TARGET(CALL_PY_WITH_DEFAULTS) { @@ -3876,7 +3881,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; uint32_t func_version = read_u32(&next_instr[1].cache); - #line 2727 "Python/bytecodes.c" + #line 2732 "Python/bytecodes.c" assert(kwnames == NULL); DEOPT_IF(tstate->interp->eval_frame, CALL); int is_meth = method != NULL; @@ -3912,7 +3917,7 @@ JUMPBY(INLINE_CACHE_ENTRIES_CALL); frame->return_offset = 0; DISPATCH_INLINED(new_frame); - #line 3916 "Python/generated_cases.c.h" + #line 3921 "Python/generated_cases.c.h" } TARGET(CALL_NO_KW_TYPE_1) { @@ -3920,7 +3925,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2765 "Python/bytecodes.c" + #line 2770 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3930,7 +3935,7 @@ res = Py_NewRef(Py_TYPE(obj)); Py_DECREF(obj); Py_DECREF(&PyType_Type); // I.e., callable - #line 3934 "Python/generated_cases.c.h" + #line 3939 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3943,7 +3948,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2777 "Python/bytecodes.c" + #line 2782 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3954,7 +3959,7 @@ Py_DECREF(arg); Py_DECREF(&PyUnicode_Type); // I.e., callable if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3958 "Python/generated_cases.c.h" + #line 3963 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3968,7 +3973,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *null = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2791 "Python/bytecodes.c" + #line 2796 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); DEOPT_IF(null != NULL, CALL); @@ -3979,7 +3984,7 @@ Py_DECREF(arg); Py_DECREF(&PyTuple_Type); // I.e., tuple if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 3983 "Python/generated_cases.c.h" + #line 3988 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -3993,7 +3998,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2805 "Python/bytecodes.c" + #line 2810 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -4015,7 +4020,7 @@ } Py_DECREF(tp); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4019 "Python/generated_cases.c.h" + #line 4024 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4029,7 +4034,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2830 "Python/bytecodes.c" + #line 2835 "Python/bytecodes.c" /* Builtin METH_O functions */ assert(kwnames == NULL); int is_meth = method != NULL; @@ -4057,7 +4062,7 @@ Py_DECREF(arg); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4061 "Python/generated_cases.c.h" + #line 4066 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4071,7 +4076,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2861 "Python/bytecodes.c" + #line 2866 "Python/bytecodes.c" /* Builtin METH_FASTCALL functions, without keywords */ assert(kwnames == NULL); int is_meth = method != NULL; @@ -4103,7 +4108,7 @@ 'invalid'). In those cases an exception is set, so we must handle it. */ - #line 4107 "Python/generated_cases.c.h" + #line 4112 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4117,7 +4122,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2896 "Python/bytecodes.c" + #line 2901 "Python/bytecodes.c" /* Builtin METH_FASTCALL | METH_KEYWORDS functions */ int is_meth = method != NULL; int total_args = oparg; @@ -4149,7 +4154,7 @@ } Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4153 "Python/generated_cases.c.h" + #line 4158 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4163,7 +4168,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2931 "Python/bytecodes.c" + #line 2936 "Python/bytecodes.c" assert(kwnames == NULL); /* len(o) */ int is_meth = method != NULL; @@ -4188,7 +4193,7 @@ Py_DECREF(callable); Py_DECREF(arg); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4192 "Python/generated_cases.c.h" + #line 4197 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4201,7 +4206,7 @@ PyObject *callable = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 2958 "Python/bytecodes.c" + #line 2963 "Python/bytecodes.c" assert(kwnames == NULL); /* isinstance(o, o2) */ int is_meth = method != NULL; @@ -4228,7 +4233,7 @@ Py_DECREF(cls); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4232 "Python/generated_cases.c.h" + #line 4237 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4240,7 +4245,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *self = stack_pointer[-(1 + oparg)]; PyObject *method = stack_pointer[-(2 + oparg)]; - #line 2988 "Python/bytecodes.c" + #line 2993 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 1); assert(method != NULL); @@ -4258,14 +4263,14 @@ JUMPBY(INLINE_CACHE_ENTRIES_CALL + 1); assert(next_instr[-1].op.code == POP_TOP); DISPATCH(); - #line 4262 "Python/generated_cases.c.h" + #line 4267 "Python/generated_cases.c.h" } TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) { PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3008 "Python/bytecodes.c" + #line 3013 "Python/bytecodes.c" assert(kwnames == NULL); int is_meth = method != NULL; int total_args = oparg; @@ -4296,7 +4301,7 @@ Py_DECREF(arg); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4300 "Python/generated_cases.c.h" + #line 4305 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4309,7 +4314,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3042 "Python/bytecodes.c" + #line 3047 "Python/bytecodes.c" int is_meth = method != NULL; int total_args = oparg; if (is_meth) { @@ -4338,7 +4343,7 @@ } Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4342 "Python/generated_cases.c.h" + #line 4347 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4351,7 +4356,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3074 "Python/bytecodes.c" + #line 3079 "Python/bytecodes.c" assert(kwnames == NULL); assert(oparg == 0 || oparg == 1); int is_meth = method != NULL; @@ -4380,7 +4385,7 @@ Py_DECREF(self); Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4384 "Python/generated_cases.c.h" + #line 4389 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4393,7 +4398,7 @@ PyObject **args = (stack_pointer - oparg); PyObject *method = stack_pointer[-(2 + oparg)]; PyObject *res; - #line 3106 "Python/bytecodes.c" + #line 3111 "Python/bytecodes.c" assert(kwnames == NULL); int is_meth = method != NULL; int total_args = oparg; @@ -4421,7 +4426,7 @@ } Py_DECREF(callable); if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; } - #line 4425 "Python/generated_cases.c.h" + #line 4430 "Python/generated_cases.c.h" STACK_SHRINK(oparg); STACK_SHRINK(1); stack_pointer[-1] = res; @@ -4431,9 +4436,9 @@ } TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { - #line 3137 "Python/bytecodes.c" + #line 3142 "Python/bytecodes.c" GO_TO_INSTRUCTION(CALL_FUNCTION_EX); - #line 4437 "Python/generated_cases.c.h" + #line 4442 "Python/generated_cases.c.h" } TARGET(CALL_FUNCTION_EX) { @@ -4442,7 +4447,7 @@ PyObject *callargs = stack_pointer[-(1 + ((oparg & 1) ? 1 : 0))]; PyObject *func = stack_pointer[-(2 + ((oparg & 1) ? 1 : 0))]; PyObject *result; - #line 3141 "Python/bytecodes.c" + #line 3146 "Python/bytecodes.c" // DICT_MERGE is called before this opcode if there are kwargs. // It converts all dict subtypes in kwargs into regular dicts. assert(kwargs == NULL || PyDict_CheckExact(kwargs)); @@ -4504,14 +4509,14 @@ } result = PyObject_Call(func, callargs, kwargs); } - #line 4508 "Python/generated_cases.c.h" + #line 4513 "Python/generated_cases.c.h" Py_DECREF(func); Py_DECREF(callargs); Py_XDECREF(kwargs); - #line 3203 "Python/bytecodes.c" + #line 3208 "Python/bytecodes.c" assert(PEEK(3 + (oparg & 1)) == NULL); if (result == NULL) { STACK_SHRINK(((oparg & 1) ? 1 : 0)); goto pop_3_error; } - #line 4515 "Python/generated_cases.c.h" + #line 4520 "Python/generated_cases.c.h" STACK_SHRINK(((oparg & 1) ? 1 : 0)); STACK_SHRINK(2); stack_pointer[-1] = result; @@ -4526,7 +4531,7 @@ PyObject *kwdefaults = (oparg & 0x02) ? stack_pointer[-(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0))] : NULL; PyObject *defaults = (oparg & 0x01) ? stack_pointer[-(1 + ((oparg & 0x08) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x01) ? 1 : 0))] : NULL; PyObject *func; - #line 3213 "Python/bytecodes.c" + #line 3218 "Python/bytecodes.c" PyFunctionObject *func_obj = (PyFunctionObject *) PyFunction_New(codeobj, GLOBALS()); @@ -4555,14 +4560,14 @@ func_obj->func_version = ((PyCodeObject *)codeobj)->co_version; func = (PyObject *)func_obj; - #line 4559 "Python/generated_cases.c.h" + #line 4564 "Python/generated_cases.c.h" STACK_SHRINK(((oparg & 0x01) ? 1 : 0) + ((oparg & 0x02) ? 1 : 0) + ((oparg & 0x04) ? 1 : 0) + ((oparg & 0x08) ? 1 : 0)); stack_pointer[-1] = func; DISPATCH(); } TARGET(RETURN_GENERATOR) { - #line 3244 "Python/bytecodes.c" + #line 3249 "Python/bytecodes.c" assert(PyFunction_Check(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj; PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); @@ -4583,7 +4588,7 @@ frame = cframe.current_frame = prev; _PyFrame_StackPush(frame, (PyObject *)gen); goto resume_frame; - #line 4587 "Python/generated_cases.c.h" + #line 4592 "Python/generated_cases.c.h" } TARGET(BUILD_SLICE) { @@ -4591,15 +4596,15 @@ PyObject *stop = stack_pointer[-(1 + ((oparg == 3) ? 1 : 0))]; PyObject *start = stack_pointer[-(2 + ((oparg == 3) ? 1 : 0))]; PyObject *slice; - #line 3267 "Python/bytecodes.c" + #line 3272 "Python/bytecodes.c" slice = PySlice_New(start, stop, step); - #line 4597 "Python/generated_cases.c.h" + #line 4602 "Python/generated_cases.c.h" Py_DECREF(start); Py_DECREF(stop); Py_XDECREF(step); - #line 3269 "Python/bytecodes.c" + #line 3274 "Python/bytecodes.c" if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error; } - #line 4603 "Python/generated_cases.c.h" + #line 4608 "Python/generated_cases.c.h" STACK_SHRINK(((oparg == 3) ? 1 : 0)); STACK_SHRINK(1); stack_pointer[-1] = slice; @@ -4610,7 +4615,7 @@ PyObject *fmt_spec = ((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? stack_pointer[-((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))] : NULL; PyObject *value = stack_pointer[-(1 + (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0))]; PyObject *result; - #line 3273 "Python/bytecodes.c" + #line 3278 "Python/bytecodes.c" /* Handles f-string value formatting. */ PyObject *(*conv_fn)(PyObject *); int which_conversion = oparg & FVC_MASK; @@ -4645,7 +4650,7 @@ Py_DECREF(value); Py_XDECREF(fmt_spec); if (result == NULL) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; } - #line 4649 "Python/generated_cases.c.h" + #line 4654 "Python/generated_cases.c.h" STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); stack_pointer[-1] = result; DISPATCH(); @@ -4654,10 +4659,10 @@ TARGET(COPY) { PyObject *bottom = stack_pointer[-(1 + (oparg-1))]; PyObject *top; - #line 3310 "Python/bytecodes.c" + #line 3315 "Python/bytecodes.c" assert(oparg > 0); top = Py_NewRef(bottom); - #line 4661 "Python/generated_cases.c.h" + #line 4666 "Python/generated_cases.c.h" STACK_GROW(1); stack_pointer[-1] = top; DISPATCH(); @@ -4669,7 +4674,7 @@ PyObject *rhs = stack_pointer[-1]; PyObject *lhs = stack_pointer[-2]; PyObject *res; - #line 3315 "Python/bytecodes.c" + #line 3320 "Python/bytecodes.c" #if ENABLE_SPECIALIZATION _PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr; if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { @@ -4684,12 +4689,12 @@ assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops)); assert(binary_ops[oparg]); res = binary_ops[oparg](lhs, rhs); - #line 4688 "Python/generated_cases.c.h" + #line 4693 "Python/generated_cases.c.h" Py_DECREF(lhs); Py_DECREF(rhs); - #line 3330 "Python/bytecodes.c" + #line 3335 "Python/bytecodes.c" if (res == NULL) goto pop_2_error; - #line 4693 "Python/generated_cases.c.h" + #line 4698 "Python/generated_cases.c.h" STACK_SHRINK(1); stack_pointer[-1] = res; next_instr += 1; @@ -4699,16 +4704,16 @@ TARGET(SWAP) { PyObject *top = stack_pointer[-1]; PyObject *bottom = stack_pointer[-(2 + (oparg-2))]; - #line 3335 "Python/bytecodes.c" + #line 3340 "Python/bytecodes.c" assert(oparg >= 2); - #line 4705 "Python/generated_cases.c.h" + #line 4710 "Python/generated_cases.c.h" stack_pointer[-1] = bottom; stack_pointer[-(2 + (oparg-2))] = top; DISPATCH(); } TARGET(INSTRUMENTED_INSTRUCTION) { - #line 3339 "Python/bytecodes.c" + #line 3344 "Python/bytecodes.c" int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, next_instr-1); if (next_opcode < 0) goto error; @@ -4720,26 +4725,26 @@ assert(next_opcode > 0 && next_opcode < 256); opcode = next_opcode; DISPATCH_GOTO(); - #line 4724 "Python/generated_cases.c.h" + #line 4729 "Python/generated_cases.c.h" } TARGET(INSTRUMENTED_JUMP_FORWARD) { - #line 3353 "Python/bytecodes.c" + #line 3358 "Python/bytecodes.c" INSTRUMENTED_JUMP(next_instr-1, next_instr+oparg, PY_MONITORING_EVENT_JUMP); - #line 4730 "Python/generated_cases.c.h" + #line 4735 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_JUMP_BACKWARD) { - #line 3357 "Python/bytecodes.c" + #line 3362 "Python/bytecodes.c" INSTRUMENTED_JUMP(next_instr-1, next_instr-oparg, PY_MONITORING_EVENT_JUMP); - #line 4737 "Python/generated_cases.c.h" + #line 4742 "Python/generated_cases.c.h" CHECK_EVAL_BREAKER(); DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_TRUE) { - #line 3362 "Python/bytecodes.c" + #line 3367 "Python/bytecodes.c" PyObject *cond = POP(); int err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -4748,12 +4753,12 @@ assert(err == 0 || err == 1); int offset = err*oparg; INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4752 "Python/generated_cases.c.h" + #line 4757 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_FALSE) { - #line 3373 "Python/bytecodes.c" + #line 3378 "Python/bytecodes.c" PyObject *cond = POP(); int err = PyObject_IsTrue(cond); Py_DECREF(cond); @@ -4762,12 +4767,12 @@ assert(err == 0 || err == 1); int offset = (1-err)*oparg; INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4766 "Python/generated_cases.c.h" + #line 4771 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_NONE) { - #line 3384 "Python/bytecodes.c" + #line 3389 "Python/bytecodes.c" PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; @@ -4779,12 +4784,12 @@ offset = 0; } INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4783 "Python/generated_cases.c.h" + #line 4788 "Python/generated_cases.c.h" DISPATCH(); } TARGET(INSTRUMENTED_POP_JUMP_IF_NOT_NONE) { - #line 3398 "Python/bytecodes.c" + #line 3403 "Python/bytecodes.c" PyObject *value = POP(); _Py_CODEUNIT *here = next_instr-1; int offset; @@ -4796,30 +4801,30 @@ offset = oparg; } INSTRUMENTED_JUMP(here, next_instr + offset, PY_MONITORING_EVENT_BRANCH); - #line 4800 "Python/generated_cases.c.h" + #line 4805 "Python/generated_cases.c.h" DISPATCH(); } TARGET(EXTENDED_ARG) { - #line 3412 "Python/bytecodes.c" + #line 3417 "Python/bytecodes.c" assert(oparg); opcode = next_instr->op.code; oparg = oparg << 8 | next_instr->op.arg; PRE_DISPATCH_GOTO(); DISPATCH_GOTO(); - #line 4811 "Python/generated_cases.c.h" + #line 4816 "Python/generated_cases.c.h" } TARGET(CACHE) { - #line 3420 "Python/bytecodes.c" + #line 3425 "Python/bytecodes.c" assert(0 && "Executing a cache."); Py_UNREACHABLE(); - #line 4818 "Python/generated_cases.c.h" + #line 4823 "Python/generated_cases.c.h" } TARGET(RESERVED) { - #line 3425 "Python/bytecodes.c" + #line 3430 "Python/bytecodes.c" assert(0 && "Executing RESERVED instruction."); Py_UNREACHABLE(); - #line 4825 "Python/generated_cases.c.h" + #line 4830 "Python/generated_cases.c.h" } diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 37933ff..05a53d0 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -696,29 +696,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; @@ -773,7 +757,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 @@ -915,7 +899,7 @@ get_tools_for_instruction(PyCodeObject * code, int i, int event) event == PY_MONITORING_EVENT_C_RETURN); event = PY_MONITORING_EVENT_CALL; } - if (event < PY_MONITORING_INSTRUMENTED_EVENTS && monitoring->tools) { + if (PY_MONITORING_IS_INSTRUMENTED_EVENT(event) && monitoring->tools) { tools = monitoring->tools[i]; } else { @@ -926,6 +910,26 @@ get_tools_for_instruction(PyCodeObject * code, int i, int event) 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, @@ -973,7 +977,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); @@ -1251,7 +1266,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); } @@ -2024,26 +2039,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]*/ |