https://github.com/python/cpython/commit/e9c9a339035c9b96a5ebca8337a13140725ecf2a
commit: e9c9a339035c9b96a5ebca8337a13140725ecf2a
branch: main
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-11-03T08:23:27Z
summary:
gh-161233: Fix `TypeError` when `timer=None` was passed to `cProfile.Profile`
(#161234)
files:
A Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst
M Lib/test/test_profiling/test_tracing_profiler.py
M Modules/_lsprof.c
diff --git a/Lib/test/test_profiling/test_tracing_profiler.py
b/Lib/test/test_profiling/test_tracing_profiler.py
index 7e2ed24f4918e82..ac8fdf343b4fd16 100644
--- a/Lib/test/test_profiling/test_tracing_profiler.py
+++ b/Lib/test/test_profiling/test_tracing_profiler.py
@@ -139,6 +139,20 @@ def timer():
profiler.disable()
profiler.clear()
+ def test_external_timer_is_none(self):
+ # gh-161233
+ def work():
+ pass
+
+ for kwargs in ({}, {'timer': None}):
+ with self.subTest(kwargs=kwargs):
+ profiler = cProfile.Profile(**kwargs)
+ profiler.enable()
+ with support.catch_unraisable_exception() as cm:
+ work()
+ self.assertIsNone(cm.unraisable)
+ profiler.disable()
+
def test_profile_enable_disable(self):
prof = self.profilerclass()
# Make sure we clean ourselves up if the test fails for some reason.
diff --git
a/Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst
b/Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst
new file mode 100644
index 000000000000000..96e9f5e39df3ec1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst
@@ -0,0 +1,2 @@
+Fix unraisable :exc:`TypeError` when ``None`` was passed as a *timer* to
+:class:`cProfile.Profile <profile.Profile>`.
diff --git a/Modules/_lsprof.c b/Modules/_lsprof.c
index 42fd1eaa0f088a5..c11973d3ed1ff0f 100644
--- a/Modules/_lsprof.c
+++ b/Modules/_lsprof.c
@@ -92,6 +92,7 @@ _lsprof_get_state(PyObject *module)
static PyTime_t CallExternalTimer(ProfilerObject *pObj)
{
+ assert(pObj->externalTimer != NULL && pObj->externalTimer != Py_None);
PyObject *o = _PyObject_CallNoArgs(pObj->externalTimer);
if (o == NULL) {
@@ -1031,6 +1032,9 @@ profiler_init_impl(ProfilerObject *self, PyObject *timer,
double timeunit,
if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) {
return -1;
}
+ if (timer == Py_None) {
+ timer = NULL;
+ }
self->externalTimerUnit = timeunit;
Py_XSETREF(self->externalTimer, Py_XNewRef(timer));
self->tool_id = PY_MONITORING_PROFILER_ID;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]