Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions Lib/test/test_profiling/test_tracing_profiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,28 @@ def gen():

self.assertTrue(any("throw" in func[2] for func in pr.stats.keys())),

def test_clear_with_nested_calls(self):
# Calling clear() during nested profiled calls should not leak
# ProfilerContexts. clearEntries() must walk the entire linked list,
# not just free the top context.
import _lsprof

def level3(profiler):
profiler.clear()

def level2(profiler):
level3(profiler)

def level1(profiler):
level2(profiler)

p = _lsprof.Profiler()
p.enable()
for _ in range(100):
level1(p)
p.disable()
p.clear()

def test_bad_descriptor(self):
# gh-132250
# cProfile should not crash when the profiler callback fails to locate
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix memory leak in ``_lsprof`` when ``clear()`` is called during active
profiling with nested calls. ``clearEntries()`` now walks the entire
``currentProfilerContext`` linked list instead of only freeing the top context.
7 changes: 4 additions & 3 deletions Modules/_lsprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,10 @@ static void clearEntries(ProfilerObject *pObj)
RotatingTree_Enum(pObj->profilerEntries, freeEntry, NULL);
pObj->profilerEntries = EMPTY_ROTATING_TREE;
/* release the memory hold by the ProfilerContexts */
if (pObj->currentProfilerContext) {
PyMem_Free(pObj->currentProfilerContext);
pObj->currentProfilerContext = NULL;
while (pObj->currentProfilerContext) {
ProfilerContext *c = pObj->currentProfilerContext;
pObj->currentProfilerContext = c->previous;
PyMem_Free(c);
}
while (pObj->freelistProfilerContext) {
ProfilerContext *c = pObj->freelistProfilerContext;
Expand Down
Loading