Skip to content

Commit e8ab41d

Browse files
committed
Fix another race with tracing
1 parent e79ed43 commit e8ab41d

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

Lib/test/test_free_threading/test_monitoring.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,38 @@ def noop():
413413

414414
self.observe_threads(noop, buf)
415415

416+
def test_trace_concurrent(self):
417+
# Test calling a function concurrently from a tracing and a non-tracing
418+
# thread
419+
b = threading.Barrier(2)
420+
421+
def func():
422+
for _ in range(100):
423+
pass
424+
425+
def noop():
426+
pass
427+
428+
def bg_thread():
429+
b.wait()
430+
func() # this may instrument `func`
431+
432+
def tracefunc(frame, event, arg):
433+
# These calls run under tracing can race with the background thread
434+
for _ in range(10):
435+
func()
436+
return tracefunc
437+
438+
t = Thread(target=bg_thread)
439+
t.start()
440+
try:
441+
sys.settrace(tracefunc)
442+
b.wait()
443+
noop()
444+
finally:
445+
sys.settrace(None)
446+
t.join()
447+
416448

417449
if __name__ == "__main__":
418450
unittest.main()

Python/bytecodes.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,15 @@ dummy_func(
181181
}
182182

183183
tier1 op(_MAYBE_INSTRUMENT, (--)) {
184-
if (tstate->tracing == 0) {
184+
#ifdef Py_GIL_DISABLED
185+
// For thread-safety, we need to check instrumentation version
186+
// even when tracing. Otherwise, another thread may concurrently
187+
// re-write the bytecode while we are executing this function.
188+
int check_instrumentation = 1;
189+
#else
190+
int check_instrumentation = (tstate->tracing == 0);
191+
#endif
192+
if (check_instrumentation) {
185193
uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
186194
uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
187195
if (code_version != global_version) {

Python/generated_cases.c.h

Lines changed: 14 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)