mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-122029: Do not unpack method for legacy tracing anymore (#130898)
This commit is contained in:
parent
3569e4a670
commit
8b1edae93a
3 changed files with 22 additions and 13 deletions
|
@ -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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -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.
|
|
@ -121,19 +121,6 @@ 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…
Add table
Add a link
Reference in a new issue