Bug description
I found stale TLBC arrays in some cases, which may result in incorrect LocationInfo.
The main issue is that tlbc_generation is incremented when thread TLBC indices are allocated or released, but when a TLBC array is modified, the profiler cannot detect the change. This may cause some problems:
- If the TLBC array grows, a new tlbc_index may keep triggering this error:
PyErr_Format(PyExc_RuntimeError,
"Invalid tlbc_index %d (array size %zd, corrupted remote memory)",
tlbc_index, tlbc_entry->tlbc_array_size);
- When a slot in the TLBC array changes from NULL to tlbc_bytecode_addr, the profiler cannot read the updated slot from its cache. A similar issue occurs when a slot is cleared.
# Linux: ./python -X gil=0 -X tlbc=1 repro_tlbc_bounds.py
import os, threading, time
from _remote_debugging import RemoteUnwinder
go = threading.Event()
stop = threading.Event()
def leaf():
stop.wait()
threading.Thread(target=leaf, daemon=True).start()
for _ in range(16):
threading.Thread(target=stop.wait, daemon=True).start()
threading.Thread(target=lambda: (go.wait(), leaf()), daemon=True).start()
time.sleep(0.1)
u = RemoteUnwinder(os.getpid(), all_threads=True, cache_frames=False)
u.get_stack_trace()
go.set()
time.sleep(0.1)
u.get_stack_trace() # RuntimeError: Invalid tlbc_index 18 (array size 16, ...)
import os, threading, time
from _remote_debugging import RemoteUnwinder
go = threading.Event()
stop = threading.Event()
def leaf():
stop.wait()
def lines(u):
return sorted(f.location.lineno for i in u.get_stack_trace()
for t in i.threads for f in t.frame_info
if f.funcname == "leaf")
threading.Thread(target=leaf, daemon=True).start()
threading.Thread(target=lambda: (go.wait(), leaf()), daemon=True).start()
time.sleep(0.1)
u = RemoteUnwinder(os.getpid(), all_threads=True, cache_frames=False)
print("Before:", lines(u))
go.set()
time.sleep(0.1)
print("Cached:", lines(u))
print("Fresh: ", lines(RemoteUnwinder(
os.getpid(), all_threads=True, cache_frames=False)))
Before: [8]
Cached: [-1, 8]
Fresh: [8, 8]
CPython versions tested on
3.15
Operating systems tested on
Linux
Linked PRs
Bug description
I found stale TLBC arrays in some cases, which may result in incorrect LocationInfo.
The main issue is that tlbc_generation is incremented when thread TLBC indices are allocated or released, but when a TLBC array is modified, the profiler cannot detect the change. This may cause some problems:
CPython versions tested on
3.15
Operating systems tested on
Linux
Linked PRs