]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109371: Fix monitoring with instruction events set (gh-109385)
authorTian Gao <gaogaotiantian@hotmail.com>
Mon, 18 Sep 2023 14:30:08 +0000 (07:30 -0700)
committerGitHub <noreply@github.com>
Mon, 18 Sep 2023 14:30:08 +0000 (23:30 +0900)
Lib/test/test_monitoring.py
Lib/test/test_sys_setprofile.py
Misc/NEWS.d/next/Core and Builtins/2023-09-13-21-04-04.gh-issue-109371.HPEJr8.rst [new file with mode: 0644]
Python/instrumentation.c

index 992d3cc8b6d7f9b707012c63b83cdd8619a1b8a0..2100d998ff0808b6aa3cb072049fb122b749cf39 100644 (file)
@@ -501,6 +501,22 @@ class MultipleMonitorsTest(MonitoringTestBase, unittest.TestCase):
             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):
index 49e076c77d167ae347753dac11115a4e93e7e471..34c70d6c8de0c458b9236e20fee822c2cf1d41bc 100644 (file)
@@ -439,7 +439,6 @@ class TestEdgeCases(unittest.TestCase):
         sys.setprofile(foo)
         self.assertEqual(sys.getprofile(), bar)
 
-
     def test_same_object(self):
         def foo(*args):
             ...
@@ -448,6 +447,18 @@ class TestEdgeCases(unittest.TestCase):
         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 (file)
index 0000000..2fb18d5
--- /dev/null
@@ -0,0 +1 @@
+Deopted instructions correctly for tool initialization and modified the incorrect assertion in instrumentation, when a previous tool already sets INSTRUCTION events
index 0768c82ba29882e6cb469eb589873b900c007bc8..df8943b1f9a7212886da0f7532c42c88c54a6ab3 100644 (file)
@@ -664,7 +664,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);
@@ -1295,6 +1295,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];