summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-07-28 09:53:33 (GMT)
committerGitHub <noreply@github.com>2023-07-28 09:53:33 (GMT)
commit0902afbae29ef88bf9d212a7e11f9f17b6cbdeb5 (patch)
treeeeada04f808fc41bfeb35fb8ac87dd3297c9a037
parent3b1a4c18426c78a2fda0d59728bfe9eb92889722 (diff)
downloadcpython-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.h3
-rw-r--r--Lib/test/test_monitoring.py52
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2023-07-26-18-53-34.gh-issue-106895.DdEwV8.rst2
-rw-r--r--Objects/classobject.c2
-rw-r--r--Python/bytecodes.c7
-rw-r--r--Python/ceval.c13
-rw-r--r--Python/generated_cases.c.h193
-rw-r--r--Python/instrumentation.c79
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]*/