summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-03-29 19:33:06 (GMT)
committerGitHub <noreply@github.com>2024-03-29 19:33:06 (GMT)
commit01bd74eadbc4ff839d39762fae6366f50c1e116e (patch)
treedad7fd5f31389305e80f6989b371e2b97b7b4fdb
parent94c97423a9c4969f8ddd4a3aa4aacb99c4d5263d (diff)
downloadcpython-01bd74eadbc4ff839d39762fae6366f50c1e116e.zip
cpython-01bd74eadbc4ff839d39762fae6366f50c1e116e.tar.gz
cpython-01bd74eadbc4ff839d39762fae6366f50c1e116e.tar.bz2
gh-117300: Use stop the world to make `sys._current_frames` and `sys._current_exceptions` thread-safe. (#117301)
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.
-rw-r--r--Lib/test/test_sys.py3
-rw-r--r--Python/pystate.c4
2 files changed, 6 insertions, 1 deletions
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 37c16cd..f6f23b0 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -562,7 +562,8 @@ class SysModuleTest(unittest.TestCase):
# 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()
diff --git a/Python/pystate.c b/Python/pystate.c
index 8489f53..8bec727 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2408,6 +2408,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) {
@@ -2441,6 +2442,7 @@ fail:
done:
HEAD_UNLOCK(runtime);
+ _PyEval_StartTheWorldAll(runtime);
return result;
}
@@ -2472,6 +2474,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) {
@@ -2504,6 +2507,7 @@ fail:
done:
HEAD_UNLOCK(runtime);
+ _PyEval_StartTheWorldAll(runtime);
return result;
}