Skip to content

Commit

Permalink
pythongh-117300: Use stop the world to make sys._current_frames and
Browse files Browse the repository at this point in the history
`sys._current_exceptions` thread-safe.

This adds a stop the world pause to make the two functions thread-safe
when the GIL is disabled in the free-threaded build.

Additionally, the main test thread may call `sys._current_exceptions()`
as soon as `g_raised.set()` is called. The background thread may not yet
reach the `leave_g.wait()` line.
  • Loading branch information
colesbury committed Mar 27, 2024
1 parent 262fb91 commit 17a405e
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,8 @@ def g456():
# And the next record must be for g456().
filename, lineno, funcname, sourceline = stack[i+1]
self.assertEqual(funcname, "g456")
self.assertTrue(sourceline.startswith("if leave_g.wait("))
self.assertTrue((sourceline.startswith("if leave_g.wait(") or
sourceline.startswith("g_raised.set()")))
finally:
# Reap the spawned thread.
leave_g.set()
Expand Down
4 changes: 4 additions & 0 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2406,6 +2406,7 @@ _PyThread_CurrentFrames(void)
* Because these lists can mutate even when the GIL is held, we
* need to grab head_mutex for the duration.
*/
_PyEval_StopTheWorldAll(runtime);
HEAD_LOCK(runtime);
PyInterpreterState *i;
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
Expand Down Expand Up @@ -2439,6 +2440,7 @@ _PyThread_CurrentFrames(void)

done:
HEAD_UNLOCK(runtime);
_PyEval_StartTheWorldAll(runtime);
return result;
}

Expand Down Expand Up @@ -2470,6 +2472,7 @@ _PyThread_CurrentExceptions(void)
* Because these lists can mutate even when the GIL is held, we
* need to grab head_mutex for the duration.
*/
_PyEval_StopTheWorldAll(runtime);
HEAD_LOCK(runtime);
PyInterpreterState *i;
for (i = runtime->interpreters.head; i != NULL; i = i->next) {
Expand Down Expand Up @@ -2502,6 +2505,7 @@ _PyThread_CurrentExceptions(void)

done:
HEAD_UNLOCK(runtime);
_PyEval_StartTheWorldAll(runtime);
return result;
}

Expand Down

0 comments on commit 17a405e

Please sign in to comment.