Skip to content

Commit 9d06626

Browse files
henryiiirwgk
andauthored
docs: more warnings about locking and the GIL (#5689)
* docs: more warnings about locking and the GIL Signed-off-by: Henry Schreiner <[email protected]> * fix require → reacquire typo --------- Signed-off-by: Henry Schreiner <[email protected]> Co-authored-by: Ralf W. Grosse-Kunstleve <[email protected]>
1 parent d7769de commit 9d06626

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

docs/advanced/misc.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,17 @@ However, the module is no longer free-threading safe, for the same reason as
299299
before, because the calculation is not synchronized. We can synchronize it
300300
using a Python critical section. This will do nothing if not in free-threaded
301301
Python. You can have it lock one or two Python objects. You cannot nest it.
302-
(Note: In Python 3.13t, Python re-locks if you enter a critical section again,
303-
which happens in various places. This was optimized away in 3.14+. Use a
304-
``std::mutex`` instead if this is a problem).
302+
303+
.. warning::
304+
305+
When using a ``py::scoped_critical_section``, make sure it is not nested and
306+
that no other synchronization primitives (such as a ``std::mutex``) are
307+
held, which could lead to deadlocks. In 3.13, taking the same lock causes it
308+
to release then reacquire, which means you can't use it to, for example, read
309+
and write to a dictionary, because the dictionary uses a critical section
310+
internally in CPython. Use a ``std::mutex`` instead if you need this on
311+
Python 3.13. In 3.14, taking a lock on a locked object no longer releases
312+
and relocks as an optimization, which also fixes this case.
305313

306314
.. code-block:: cpp
307315
:emphasize-lines: 1,4,8

tests/test_embed/test_interpreter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,13 @@ TEST_CASE("Threads") {
365365
py::gil_scoped_acquire gil{};
366366
#ifdef Py_GIL_DISABLED
367367
# if PY_VERSION_HEX < 0x030E0000
368+
// This will not run with the GIL, so it won't deadlock. That's
369+
// because of how we run our tests. Be more careful of
370+
// deadlocks if the "free-threaded" GIL could be enabled (at
371+
// runtime).
368372
std::lock_guard<std::mutex> lock(mutex);
369373
# else
374+
// CPython's thread-safe API in no-GIL mode.
370375
py::scoped_critical_section lock(locals);
371376
# endif
372377
#endif

0 commit comments

Comments
 (0)