Ok, I was able to repro the issue. The problem -- or at least one of the problems -- is that when stopping tracemalloc we set the ctx back to NULL. Another thread can see an inconsistency: it may call tracemalloc_alloc but without the right context.
It's a lot easier to repro on the free threading build, but the reported crashes are all with the GIL enabled.
If I understood correctly, there is a race condition between:
Thread A calls tracemalloc.stop() which calls PyMem_SetAllocator() to change memory allocators (functions+ctx pointer).
Thread B calls PyTraceMalloc_Track() which calls PyGILState_Ensure() which calls PyMem_RawCalloc().
There is basically no synchronization between thread A and thread B, and so thread B can get an inconsistent state when calling a memory allocator: ctx doesn't match the allocator function.
PyMem_SetAllocator() uses ALLOCATORS_MUTEX, but allocator functions such as PyMem_RawMalloc() don't use this lock.
The test spawns 50 native threads which only gets a temporary thread state when calling PyTraceMalloc_Track() and PyTraceMalloc_Untrack(). The thread C function:
Activity
colesbury commented on Dec 24, 2025
cc @kumaraditya303
colesbury commented on Dec 24, 2025
Might be related to:
VanshAgarwal24036 commented on Dec 25, 2025
Hello, I wanted to check whether this issue is still available to work on. If no one is currently handling it, I’d like to contribute. Thanks!
kumaraditya303 commented on Feb 9, 2026
I am not able to reproduce this even after running it in a loop for 100k times.
threexc commented on Feb 26, 2026
We are seeing this in the Yocto Autobuilder (CI) system intermittently: https://bugzilla.yoctoproject.org/show_bug.cgi?id=16182
It's happening on an arm64-based Debian host, running the tests inside qemuarm64.
EDIT: also, it occurred using Python 3.13.
colesbury commented on Feb 26, 2026
Also occurred again (~8 days ago) on the Raspbian after Victor's latest tracemalloc fix:
https://buildbot.python.org/#/builders/424/builds/12867
colesbury commented on Feb 26, 2026
Ok, I was able to repro the issue. The problem -- or at least one of the problems -- is that when stopping tracemalloc we set the ctx back to NULL. Another thread can see an inconsistency: it may call tracemalloc_alloc but without the right context.
It's a lot easier to repro on the free threading build, but the reported crashes are all with the GIL enabled.
You can also increase the chance in a GIL-enabled build, by changing PyMem_RawMalloc to:
vstinner commented on Mar 18, 2026
If I understood correctly, there is a race condition between:
There is basically no synchronization between thread A and thread B, and so thread B can get an inconsistent state when calling a memory allocator: ctx doesn't match the allocator function.
PyMem_SetAllocator() uses ALLOCATORS_MUTEX, but allocator functions such as PyMem_RawMalloc() don't use this lock.
The test spawns 50 native threads which only gets a temporary thread state when calling PyTraceMalloc_Track() and PyTraceMalloc_Untrack(). The thread C function:
python3: skiptest tracemalloc_track_race
python3: skiptest tracemalloc_track_race
python3: skiptest tracemalloc_track_race
python3: skiptest tracemalloc_track_race
python3: skiptest tracemalloc_track_race
python3: skiptest tracemalloc_track_race
python3: skiptest tracemalloc_track_race