https://github.com/python/cpython/commit/e875c0a141cdfa5636b5fe9062a25c4dc19946e8
commit: e875c0a141cdfa5636b5fe9062a25c4dc19946e8
branch: 3.14
author: sobolevn <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-11-03T09:05:57Z
summary:

[3.14] gh-161233: Fix `TypeError` when `timer=None` was passed to 
`cProfile.Profile` (GH-161234) (#161239)

* [3.14] gh-161233: Fix `TypeError` when `timer=None` was passed to 
`cProfile.Profile` (GH-161234)
(cherry picked from commit e9c9a339035c9b96a5ebca8337a13140725ecf2a)

Co-authored-by: sobolevn <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-11-03-10-33-33.gh-issue-161233._9VrfL.rst
M Lib/test/test_cprofile.py
M Modules/_lsprof.c

diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py
index 5230348c0eb68f..656143a399a7ff 100644
--- a/Lib/test/test_cprofile.py
+++ b/Lib/test/test_cprofile.py
@@ -105,6 +105,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 00000000000000..96e9f5e39df3ec
--- /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 237919e889ca0c..a157d808d7bd19 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 = NULL;
 
     // External timer can do arbitrary things so we need a flag to prevent
@@ -1021,6 +1022,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]

Reply via email to