]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-122029: Do not unpack method for legacy tracing anymore (#130898)
authorTian Gao <gaogaotiantian@hotmail.com>
Tue, 11 Mar 2025 18:04:22 +0000 (14:04 -0400)
committerGitHub <noreply@github.com>
Tue, 11 Mar 2025 18:04:22 +0000 (14:04 -0400)
Lib/test/test_sys_setprofile.py
Misc/NEWS.d/next/Core_and_Builtins/2025-03-05-21-52-20.gh-issue-122029.d_z93q.rst [new file with mode: 0644]
Python/legacy_tracing.c

index 0753a9d8b8e0ee26eb85de3611436fe5f422c995..345c022bd2374c763367f961771b91c874fc1b27 100644 (file)
@@ -511,6 +511,27 @@ class TestEdgeCases(unittest.TestCase):
             ]
         )
 
+        # Test CALL_FUNCTION_EX
+        events = []
+        sys.setprofile(lambda frame, event, args: events.append(event))
+        # Not important, we only want to trigger INSTRUMENTED_CALL_KW
+        args = (1,)
+        m = B().f
+        m(*args, key=lambda x: 0)
+        sys.setprofile(None)
+        # The last c_call is the call to sys.setprofile
+        # INSTRUMENTED_CALL_FUNCTION_EX has different behavior than the other
+        # instrumented call bytecodes, it does not unpack the callable before
+        # calling it. This is probably not ideal because it's not consistent,
+        # but at least we get a consistent call stack (no unmatched c_call).
+        self.assertEqual(
+            events,
+            ['call', 'return',
+             'call', 'return',
+             'c_call'
+            ]
+        )
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-03-05-21-52-20.gh-issue-122029.d_z93q.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-05-21-52-20.gh-issue-122029.d_z93q.rst
new file mode 100644 (file)
index 0000000..6324f24
--- /dev/null
@@ -0,0 +1 @@
+:func:`sys.setprofile` and :func:`sys.settrace` will not generate a ``c_call`` event for ``INSTRUMENTED_CALL_FUNCTION_EX`` if the callable is a method with a C function wrapped, because we do not generate ``c_return`` event in such case.
index 97634f9183c7d547075705599dbd9bf8c9c235d8..82465c66ab5231a58b2895fcb9eadc970101034d 100644 (file)
@@ -121,19 +121,6 @@ sys_profile_call_or_return(
         Py_DECREF(meth);
         return res;
     }
-    else if (Py_TYPE(callable) == &PyMethod_Type) {
-        // CALL instruction will grab the function from the method,
-        // so if the function is a C function, the return event will
-        // be emitted. However, CALL event happens before CALL
-        // instruction, so we need to handle this case here.
-        PyObject* func = PyMethod_GET_FUNCTION(callable);
-        if (func == NULL) {
-            return NULL;
-        }
-        if (PyCFunction_Check(func)) {
-            return call_profile_func(self, func);
-        }
-    }
     Py_RETURN_NONE;
 }