Skip to content

Commit 9af8adb

Browse files
authored
Subinterpreter creation concurrency issues in 3.12 (#5779)
* Seems like 3.12 has concurrency issues when creating a subinterpreter, easiest workaround is just to lock during it. * Only need this for PER_INTERPRETER_GIL
1 parent 6972597 commit 9af8adb

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

include/pybind11/subinterpreter.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class subinterpreter {
7777
/// @note This function acquires (and then releases) the main interpreter GIL, but the main
7878
/// interpreter and its GIL are not required to be held prior to calling this function.
7979
static inline subinterpreter create(PyInterpreterConfig const &cfg) {
80+
8081
error_scope err_scope;
8182
subinterpreter result;
8283
{
@@ -85,7 +86,21 @@ class subinterpreter {
8586

8687
auto prev_tstate = PyThreadState_Get();
8788

88-
auto status = Py_NewInterpreterFromConfig(&result.creation_tstate_, &cfg);
89+
PyStatus status;
90+
91+
{
92+
/*
93+
Several internal CPython modules are lacking proper subinterpreter support in 3.12
94+
even though it is "stable" in that version. This most commonly seems to cause
95+
crashes when two interpreters concurrently initialize, which imports several things
96+
(like builtins, unicode, codecs).
97+
*/
98+
#if PY_VERSION_HEX < 0x030D0000 && defined(Py_MOD_PER_INTERPRETER_GIL_SUPPORTED)
99+
static std::mutex one_at_a_time;
100+
std::lock_guard<std::mutex> guard(one_at_a_time);
101+
#endif
102+
status = Py_NewInterpreterFromConfig(&result.creation_tstate_, &cfg);
103+
}
89104

90105
// this doesn't raise a normal Python exception, it provides an exit() status code.
91106
if (PyStatus_Exception(status)) {
@@ -117,6 +132,7 @@ class subinterpreter {
117132
// same as the default config in the python docs
118133
PyInterpreterConfig cfg;
119134
std::memset(&cfg, 0, sizeof(cfg));
135+
cfg.allow_threads = 1;
120136
cfg.check_multi_interp_extensions = 1;
121137
cfg.gil = PyInterpreterConfig_OWN_GIL;
122138
return create(cfg);

0 commit comments

Comments
 (0)