diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index d091572b0880d6..8c9755d2a41a2d 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -501,6 +501,22 @@ def test_two_with_disable(self): self.assertEqual(sys.monitoring._all_events(), {}) sys.monitoring.restart_events() + def test_with_instruction_event(self): + """Test that the second tool can set events with instruction events set by the first tool.""" + def f(): + pass + code = f.__code__ + + try: + self.assertEqual(sys.monitoring._all_events(), {}) + sys.monitoring.set_local_events(TEST_TOOL, code, E.INSTRUCTION | E.LINE) + sys.monitoring.set_local_events(TEST_TOOL2, code, E.LINE) + finally: + sys.monitoring.set_events(TEST_TOOL, 0) + sys.monitoring.set_events(TEST_TOOL2, 0) + self.assertEqual(sys.monitoring._all_events(), {}) + + class LineMonitoringTest(MonitoringTestBase, unittest.TestCase): def test_lines_single(self): diff --git a/Lib/test/test_sys_setprofile.py b/Lib/test/test_sys_setprofile.py index 49e076c77d167a..34c70d6c8de0c4 100644 --- a/Lib/test/test_sys_setprofile.py +++ b/Lib/test/test_sys_setprofile.py @@ -439,7 +439,6 @@ def __del__(self): sys.setprofile(foo) self.assertEqual(sys.getprofile(), bar) - def test_same_object(self): def foo(*args): ... @@ -448,6 +447,18 @@ def foo(*args): del foo sys.setprofile(sys.getprofile()) + def test_profile_after_trace_opcodes(self): + def f(): + ... + + sys._getframe().f_trace_opcodes = True + prev_trace = sys.gettrace() + sys.settrace(lambda *args: None) + f() + sys.settrace(prev_trace) + sys.setprofile(lambda *args: None) + f() + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-09-13-21-04-04.gh-issue-109371.HPEJr8.rst b/Misc/NEWS.d/next/Core and Builtins/2023-09-13-21-04-04.gh-issue-109371.HPEJr8.rst new file mode 100644 index 00000000000000..2fb18d5ae88347 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-09-13-21-04-04.gh-issue-109371.HPEJr8.rst @@ -0,0 +1 @@ +Deopted instructions correctly for tool initialization and modified the incorrect assertion in instrumentation, when a previous tool already sets INSTRUCTION events diff --git a/Python/instrumentation.c b/Python/instrumentation.c index 0a54eb67c31967..a6ff7a8a98506c 100644 --- a/Python/instrumentation.c +++ b/Python/instrumentation.c @@ -647,7 +647,7 @@ instrument(PyCodeObject *code, int i) if (opcode == INSTRUMENTED_INSTRUCTION) { opcode_ptr = &code->_co_monitoring->per_instruction_opcodes[i]; opcode = *opcode_ptr; - CHECK(!is_instrumented(opcode)); + CHECK(opcode != INSTRUMENTED_INSTRUCTION && opcode != INSTRUMENTED_LINE); CHECK(opcode == _PyOpcode_Deopt[opcode]); } CHECK(opcode != 0); @@ -1252,6 +1252,9 @@ initialize_tools(PyCodeObject *code) if (opcode == INSTRUMENTED_LINE) { opcode = code->_co_monitoring->lines[i].original_opcode; } + if (opcode == INSTRUMENTED_INSTRUCTION) { + opcode = code->_co_monitoring->per_instruction_opcodes[i]; + } bool instrumented = is_instrumented(opcode); if (instrumented) { opcode = DE_INSTRUMENT[opcode];