Skip to content

gh-144446: Fix some frame object thread-safety issues#144479

Open
colesbury wants to merge 2 commits intopython:mainfrom
colesbury:gh-144446-frame-free-threading
Open

gh-144446: Fix some frame object thread-safety issues#144479
colesbury wants to merge 2 commits intopython:mainfrom
colesbury:gh-144446-frame-free-threading

Conversation

@colesbury
Copy link
Contributor

@colesbury colesbury commented Feb 4, 2026

Fix thread-safety issues when accessing frame attributes while another thread is executing the frame:

  • Add critical section to frame_repr() to prevent races when accessing the frame's code object and line number

  • Add _Py_NO_SANITIZE_THREAD to PyUnstable_InterpreterFrame_GetLasti() to allow intentional racy reads of instr_ptr.

  • Fix take_ownership() to not write to the original frame's f_executable

Fix thread-safety issues when accessing frame attributes while another
thread is executing the frame:

- Add critical section to frame_repr() to prevent races when accessing
  the frame's code object and line number

- Add _Py_NO_SANITIZE_THREAD to PyUnstable_InterpreterFrame_GetLasti()
  to allow intentional racy reads of instr_ptr.

- Fix take_ownership() to not write to the original frame's f_executable
@colesbury
Copy link
Contributor Author

There are still some races when accessing variables through frame.f_locals, which will be address separately.

@colesbury colesbury marked this pull request as ready for review February 4, 2026 18:08
@colesbury colesbury requested a review from mpage February 4, 2026 18:37
@colesbury colesbury added the needs backport to 3.14 bugs and security fixes label Feb 4, 2026
run_with_frame(lambda frame: repr(frame))

def test_concurrent_f_trace_write(self):
"""Test writing to f_trace of a live frame."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use comments instead of docstrings because unittest renders docs string poorly when test fails.

// so we need to restore it.
frame->f_executable = PyStackRef_DUP(new_frame->f_executable);
new_frame->f_executable = PyStackRef_DUP(new_frame->f_executable);
f->f_frame = new_frame;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move this assignment after following if?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants