Skip to content

Commit 93fac8d

Browse files
authored
bpo-29676: fix lsprof can't profile C method call. (GH523)
When LOAD_METHOD is used for calling C mehtod, PyMethodDescrObject was passed to profilefunc from 5566bbb. But lsprof traces only PyCFunctionObject. Additionally, there can be some third party extension which assumes passed arg is PyCFunctionObject without calling PyCFunction_Check(). So make PyCFunctionObject from PyMethodDescrObject when tstate->c_profilefunc is set.
1 parent d36a716 commit 93fac8d

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

Python/ceval.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4818,7 +4818,20 @@ call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *kwnames)
48184818
}
48194819
else if (Py_TYPE(func) == &PyMethodDescr_Type) {
48204820
PyThreadState *tstate = PyThreadState_GET();
4821-
C_TRACE(x, _PyMethodDescr_FastCallKeywords(func, stack, nargs, kwnames));
4821+
if (tstate->use_tracing && tstate->c_profilefunc) {
4822+
// We need to create PyCFunctionObject for tracing.
4823+
PyMethodDescrObject *descr = (PyMethodDescrObject*)func;
4824+
func = PyCFunction_NewEx(descr->d_method, stack[0], NULL);
4825+
if (func == NULL) {
4826+
return NULL;
4827+
}
4828+
C_TRACE(x, _PyCFunction_FastCallKeywords(func, stack+1, nargs-1,
4829+
kwnames));
4830+
Py_DECREF(func);
4831+
}
4832+
else {
4833+
x = _PyMethodDescr_FastCallKeywords(func, stack, nargs, kwnames);
4834+
}
48224835
}
48234836
else {
48244837
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {

0 commit comments

Comments
 (0)