Skip to content

Commit 2a67003

Browse files
committed
[3.14] gh-161233: Fix TypeError when timer=None was passed to cProfile.Profile (GH-161234)
(cherry picked from commit e9c9a33) Co-authored-by: sobolevn <mail@sobolevn.me>
1 parent 79c5044 commit 2a67003

4 files changed

Lines changed: 142 additions & 0 deletions

File tree

‎Lib/test/test_cprofile.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ def timer():
105105
profiler.disable()
106106
profiler.clear()
107107

108+
def test_external_timer_is_none(self):
109+
# gh-161233
110+
def work():
111+
pass
112+
113+
for kwargs in ({}, {'timer': None}):
114+
with self.subTest(kwargs=kwargs):
115+
profiler = cProfile.Profile(**kwargs)
116+
profiler.enable()
117+
with support.catch_unraisable_exception() as cm:
118+
work()
119+
self.assertIsNone(cm.unraisable)
120+
profiler.disable()
121+
108122
def test_profile_enable_disable(self):
109123
prof = self.profilerclass()
110124
# Make sure we clean ourselves up if the test fails for some reason.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix unraisable :exc:`TypeError` when ``None`` was passed as a *timer* to
2+
:class:`cProfile.Profile <profile.Profile>`.

‎Modules/_lsprof.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ _lsprof_get_state(PyObject *module)
9292

9393
static PyTime_t CallExternalTimer(ProfilerObject *pObj)
9494
{
95+
assert(pObj->externalTimer != NULL && pObj->externalTimer != Py_None);
9596
PyObject *o = NULL;
9697

9798
// 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,
10211022
if (setSubcalls(self, subcalls) < 0 || setBuiltins(self, builtins) < 0) {
10221023
return -1;
10231024
}
1025+
if (timer == Py_None) {
1026+
timer = NULL;
1027+
}
10241028
self->externalTimerUnit = timeunit;
10251029
Py_XSETREF(self->externalTimer, Py_XNewRef(timer));
10261030
self->tool_id = PY_MONITORING_PROFILER_ID;

‎Modules/config_bootstrap.c‎

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* Generated automatically from ./Modules/config.c.in by makesetup. */
2+
/* Module configuration */
3+
4+
/* !!! !!! !!! This file is edited by the makesetup script !!! !!! !!! */
5+
6+
/* This file contains the table of built-in modules.
7+
See create_builtin() in import.c. */
8+
9+
#include "Python.h"
10+
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
16+
extern PyObject* PyInit_atexit(void);
17+
extern PyObject* PyInit_faulthandler(void);
18+
extern PyObject* PyInit_posix(void);
19+
extern PyObject* PyInit__signal(void);
20+
extern PyObject* PyInit__tracemalloc(void);
21+
extern PyObject* PyInit__suggestions(void);
22+
extern PyObject* PyInit__datetime(void);
23+
extern PyObject* PyInit__codecs(void);
24+
extern PyObject* PyInit__collections(void);
25+
extern PyObject* PyInit_errno(void);
26+
extern PyObject* PyInit__io(void);
27+
extern PyObject* PyInit_itertools(void);
28+
extern PyObject* PyInit__sre(void);
29+
extern PyObject* PyInit__sysconfig(void);
30+
extern PyObject* PyInit__thread(void);
31+
extern PyObject* PyInit_time(void);
32+
extern PyObject* PyInit__types(void);
33+
extern PyObject* PyInit__typing(void);
34+
extern PyObject* PyInit__weakref(void);
35+
extern PyObject* PyInit__abc(void);
36+
extern PyObject* PyInit__functools(void);
37+
extern PyObject* PyInit__locale(void);
38+
extern PyObject* PyInit__opcode(void);
39+
extern PyObject* PyInit__operator(void);
40+
extern PyObject* PyInit__stat(void);
41+
extern PyObject* PyInit__symtable(void);
42+
extern PyObject* PyInit_pwd(void);
43+
44+
/* -- ADDMODULE MARKER 1 -- */
45+
46+
extern PyObject* PyMarshal_Init(void);
47+
extern PyObject* PyInit__imp(void);
48+
extern PyObject* PyInit_gc(void);
49+
extern PyObject* PyInit__ast(void);
50+
extern PyObject* PyInit__tokenize(void);
51+
extern PyObject* PyInit__contextvars(void);
52+
extern PyObject* _PyWarnings_Init(void);
53+
extern PyObject* PyInit__string(void);
54+
55+
struct _inittab _PyImport_Inittab[] = {
56+
57+
{"atexit", PyInit_atexit},
58+
{"faulthandler", PyInit_faulthandler},
59+
{"posix", PyInit_posix},
60+
{"_signal", PyInit__signal},
61+
{"_tracemalloc", PyInit__tracemalloc},
62+
{"_suggestions", PyInit__suggestions},
63+
{"_datetime", PyInit__datetime},
64+
{"_codecs", PyInit__codecs},
65+
{"_collections", PyInit__collections},
66+
{"errno", PyInit_errno},
67+
{"_io", PyInit__io},
68+
{"itertools", PyInit_itertools},
69+
{"_sre", PyInit__sre},
70+
{"_sysconfig", PyInit__sysconfig},
71+
{"_thread", PyInit__thread},
72+
{"time", PyInit_time},
73+
{"_types", PyInit__types},
74+
{"_typing", PyInit__typing},
75+
{"_weakref", PyInit__weakref},
76+
{"_abc", PyInit__abc},
77+
{"_functools", PyInit__functools},
78+
{"_locale", PyInit__locale},
79+
{"_opcode", PyInit__opcode},
80+
{"_operator", PyInit__operator},
81+
{"_stat", PyInit__stat},
82+
{"_symtable", PyInit__symtable},
83+
{"pwd", PyInit_pwd},
84+
85+
/* -- ADDMODULE MARKER 2 -- */
86+
87+
/* This module lives in marshal.c */
88+
{"marshal", PyMarshal_Init},
89+
90+
/* This lives in import.c */
91+
{"_imp", PyInit__imp},
92+
93+
/* This lives in Python/Python-ast.c */
94+
{"_ast", PyInit__ast},
95+
96+
/* This lives in Python/Python-tokenize.c */
97+
{"_tokenize", PyInit__tokenize},
98+
99+
/* These entries are here for sys.builtin_module_names */
100+
{"builtins", NULL},
101+
{"sys", NULL},
102+
103+
/* This lives in gcmodule.c */
104+
{"gc", PyInit_gc},
105+
106+
/* This lives in Python/_contextvars.c */
107+
{"_contextvars", PyInit__contextvars},
108+
109+
/* This lives in _warnings.c */
110+
{"_warnings", _PyWarnings_Init},
111+
112+
/* This lives in Objects/unicodeobject.c */
113+
{"_string", PyInit__string},
114+
115+
/* Sentinel */
116+
{0, 0}
117+
};
118+
119+
120+
#ifdef __cplusplus
121+
}
122+
#endif

0 commit comments

Comments
 (0)