mirror of https://github.com/python/cpython
[3.13] gh-122029: Log call events in sys.setprofile when it's a method with c function (GH-122072) (GH-122205)
gh-122029: Log call events in sys.setprofile when it's a method with c function (GH-122072)
Log call events in sys.setprofile when it is a method with a C function.
(cherry picked from commit e91ef13861
)
Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
This commit is contained in:
parent
81f9339022
commit
40cdec6a8a
|
@ -479,6 +479,20 @@ class TestEdgeCases(unittest.TestCase):
|
||||||
sys.setprofile(lambda *args: None)
|
sys.setprofile(lambda *args: None)
|
||||||
f()
|
f()
|
||||||
|
|
||||||
|
def test_method_with_c_function(self):
|
||||||
|
# gh-122029
|
||||||
|
# When we have a PyMethodObject whose im_func is a C function, we
|
||||||
|
# should record both the call and the return. f = classmethod(repr)
|
||||||
|
# is just a way to create a PyMethodObject with a C function.
|
||||||
|
class A:
|
||||||
|
f = classmethod(repr)
|
||||||
|
events = []
|
||||||
|
sys.setprofile(lambda frame, event, args: events.append(event))
|
||||||
|
A().f()
|
||||||
|
sys.setprofile(None)
|
||||||
|
# The last c_call is the call to sys.setprofile
|
||||||
|
self.assertEqual(events, ['c_call', 'c_return', 'c_call'])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Emit ``c_call`` events in :func:`sys.setprofile` when a ``PyMethodObject`` pointing to a ``PyCFunction`` is called.
|
|
@ -121,6 +121,19 @@ sys_profile_call_or_return(
|
||||||
Py_DECREF(meth);
|
Py_DECREF(meth);
|
||||||
return res;
|
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;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue