Skip to content

Conversation

b-pass
Copy link
Contributor

@b-pass b-pass commented Jul 30, 2025

Description

Looks like just lack of good support for subinterpreters internally in 3.12. Seems like the sporadic test crashes may just be from initialization issues in CPython's internal modules (including builtin).

Also, setting threading = 1 in the interpreter config appears to fix the AssertionError when shutting down a subinterpreter, so change the default config to threading = 1.

Sample ASAN report when running w/PYTHONMALLOC=debug on ubuntu 24.04 w/python 3.12.3:

==2193843==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x507000013820 in thread T2
    #0 0x77ed5dafc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x77ed5d235c27 in unicode_decode_locale ../Objects/unicodeobject.c:3679
    #2 0x77ed5d235c27 in PyUnicode_DecodeLocale ../Objects/unicodeobject.c:3696
    #3 0x77ed5d2bf7bf in PyErr_SetFromErrnoWithFilenameObjects ../Python/errors.c:837
    #4 0x77ed5d190ce1 in method_vectorcall_NOARGS ../Objects/descrobject.c:454
    #5 0x77ed5d182c06 in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #6 0x77ed5d182c06 in PyObject_VectorcallMethod ../Objects/call.c:887
    #7 0x77ed5d3dc0ca in PyObject_CallMethodNoArgs ../Include/cpython/abstract.h:94
    #8 0x77ed5d3dc0ca in _buffered_raw_tell ../Modules/_io/bufferedio.c:743
    #9 0x77ed5d3dc1e9 in _buffered_init ../Modules/_io/bufferedio.c:824
    #10 0x77ed5d3dd024 in _io_BufferedReader___init___impl ../Modules/_io/bufferedio.c:1547
    #11 0x77ed5d3dd024 in _io_BufferedReader___init__ ../Modules/_io/clinic/bufferedio.c.h:848
    #12 0x77ed5d1fed5b in type_call ../Objects/typeobject.c:1673
    #13 0x77ed5d1827de in _PyObject_MakeTpCall ../Objects/call.c:240
    #14 0x77ed5d1834d0 in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:90
    #15 0x77ed5d1834d0 in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:77
    #16 0x77ed5d1834d0 in _PyObject_CallFunctionVa ../Objects/call.c:562
    #17 0x77ed5d183772 in _PyObject_CallFunction_SizeT ../Objects/call.c:616
    #18 0x77ed5d3d5b1d in _io_open_impl ../Modules/_io/_iomodule.c:409
    #19 0x77ed5d3d5b1d in _io_open ../Modules/_io/clinic/_iomodule.c.h:293
    #20 0x77ed5d1dfadb in cfunction_vectorcall_FASTCALL_KEYWORDS ../Objects/methodobject.c:438
    #21 0x77ed5d18339b in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #22 0x77ed5d18339b in _PyObject_CallFunctionVa ../Objects/call.c:562
    #23 0x77ed5d1841fd in callmethod ../Objects/call.c:634
    #24 0x77ed5d1841fd in _PyObject_CallMethod ../Objects/call.c:703
    #25 0x77ed5d2f3259 in create_stdio ../Python/pylifecycle.c:2364
    #26 0x77ed5d2f3d93 in init_sys_streams ../Python/pylifecycle.c:2542
    #27 0x77ed5d2f3d93 in init_interp_main ../Python/pylifecycle.c:1159
    #28 0x77ed5d2f5dc0 in new_interpreter ../Python/pylifecycle.c:2110
    #29 0x77ed5d2f5dc0 in Py_NewInterpreterFromConfig ../Python/pylifecycle.c:2140
    #30 0x5c1978aeb74a in pybind11::subinterpreter::create(PyInterpreterConfig const&) /home/user/pybind11/include/pybind11/subinterpreter.h:88
    #31 0x5c1978aeb74a in pybind11::subinterpreter::create() /home/user/pybind11/include/pybind11/subinterpreter.h:123
    #32 0x5c1978aeb74a in operator() /home/user/pybind11/tests/test_embed/test_subinterpreter.cpp:333
    #33 0x77ed5ccecdb3  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #34 0x77ed5da5ea41 in asan_thread_start ../../../../src/libsanitizer/asan/asan_interceptors.cpp:234
    #35 0x77ed5c89caa3 in start_thread nptl/pthread_create.c:447
    #36 0x77ed5c929c3b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

0x507000013820 is located 16 bytes inside of 76-byte region [0x507000013810,0x50700001385c)
allocated by thread T2 here:
    #0 0x77ed5dafd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x77ed5d1e7900 in _PyMem_DebugRawAlloc ../Objects/obmalloc.c:2096
    #2 0x77ed5d1e7900 in _PyMem_DebugRawMalloc ../Objects/obmalloc.c:2129
    #3 0x77ed5d321114 in decode_current_locale ../Python/fileutils.c:482
    #4 0x77ed5d235c0a in unicode_decode_locale ../Objects/unicodeobject.c:3654
    #5 0x77ed5d235c0a in PyUnicode_DecodeLocale ../Objects/unicodeobject.c:3696
    #6 0x77ed5d2bf7bf in PyErr_SetFromErrnoWithFilenameObjects ../Python/errors.c:837
    #7 0x77ed5d190ce1 in method_vectorcall_NOARGS ../Objects/descrobject.c:454
    #8 0x77ed5d182c06 in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #9 0x77ed5d182c06 in PyObject_VectorcallMethod ../Objects/call.c:887
    #10 0x77ed5d3dc0ca in PyObject_CallMethodNoArgs ../Include/cpython/abstract.h:94
    #11 0x77ed5d3dc0ca in _buffered_raw_tell ../Modules/_io/bufferedio.c:743
    #12 0x77ed5d3dc1e9 in _buffered_init ../Modules/_io/bufferedio.c:824
    #13 0x77ed5d3dd024 in _io_BufferedReader___init___impl ../Modules/_io/bufferedio.c:1547
    #14 0x77ed5d3dd024 in _io_BufferedReader___init__ ../Modules/_io/clinic/bufferedio.c.h:848
    #15 0x77ed5d1fed5b in type_call ../Objects/typeobject.c:1673
    #16 0x77ed5d1827de in _PyObject_MakeTpCall ../Objects/call.c:240
    #17 0x77ed5d1834d0 in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:90
    #18 0x77ed5d1834d0 in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:77
    #19 0x77ed5d1834d0 in _PyObject_CallFunctionVa ../Objects/call.c:562
    #20 0x77ed5d183772 in _PyObject_CallFunction_SizeT ../Objects/call.c:616
    #21 0x77ed5d3d5b1d in _io_open_impl ../Modules/_io/_iomodule.c:409
    #22 0x77ed5d3d5b1d in _io_open ../Modules/_io/clinic/_iomodule.c.h:293
    #23 0x77ed5d1dfadb in cfunction_vectorcall_FASTCALL_KEYWORDS ../Objects/methodobject.c:438
    #24 0x77ed5d18339b in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #25 0x77ed5d18339b in _PyObject_CallFunctionVa ../Objects/call.c:562
    #26 0x77ed5d1841fd in callmethod ../Objects/call.c:634
    #27 0x77ed5d1841fd in _PyObject_CallMethod ../Objects/call.c:703
    #28 0x77ed5d2f3259 in create_stdio ../Python/pylifecycle.c:2364
    #29 0x77ed5d2f3d93 in init_sys_streams ../Python/pylifecycle.c:2542
    #30 0x77ed5d2f3d93 in init_interp_main ../Python/pylifecycle.c:1159
    #31 0x77ed5d2f5dc0 in new_interpreter ../Python/pylifecycle.c:2110
    #32 0x77ed5d2f5dc0 in Py_NewInterpreterFromConfig ../Python/pylifecycle.c:2140
    #33 0x5c1978aeb74a in pybind11::subinterpreter::create(PyInterpreterConfig const&) /home/user/pybind11/include/pybind11/subinterpreter.h:88
    #34 0x5c1978aeb74a in pybind11::subinterpreter::create() /home/user/pybind11/include/pybind11/subinterpreter.h:123
    #35 0x5c1978aeb74a in operator() /home/user/pybind11/tests/test_embed/test_subinterpreter.cpp:333
    #36 0x77ed5ccecdb3  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #37 0x77ed5da5ea41 in asan_thread_start ../../../../src/libsanitizer/asan/asan_interceptors.cpp:234
    #38 0x77ed5c89caa3 in start_thread nptl/pthread_create.c:447

Thread T2 created by T0 here:
    #0 0x77ed5daf51f9 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:245
    #1 0x77ed5cceceb0 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xeceb0) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 0x5c1978af9146 in thread<C_A_T_C_H_T_E_S_T_6()::<lambda(int)>&, int> /usr/include/c++/13/bits/std_thread.h:164
    #3 0x5c1978af9146 in C_A_T_C_H_T_E_S_T_6 /home/user/pybind11/tests/test_embed/test_subinterpreter.cpp:392

And also

==2188194==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x518000090890 in thread T2
    #0 0x70e41d6fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0x70e41cde9457 in _PyObject_Free ../Objects/obmalloc.c:1853
    #2 0x70e41cde9457 in _PyObject_Free ../Objects/obmalloc.c:1843
    #3 0x70e41cdcbfc7 in dictresize ../Objects/dictobject.c:1569
    #4 0x70e41cdd1b9e in insertion_resize ../Objects/dictobject.c:1194
    #5 0x70e41cdd1b9e in insertdict ../Objects/dictobject.c:1261
    #6 0x70e41cd22172 in _PyEval_EvalFrameDefault Python/bytecodes.c:552
    #7 0x70e41cea091e in _PyEval_EvalFrame ../Include/internal/pycore_ceval.h:89
    #8 0x70e41cea091e in _PyEval_Vector ../Python/ceval.c:1683
    #9 0x70e41cea091e in PyEval_EvalCode ../Python/ceval.c:578
    #10 0x70e41ce9c8af in builtin_exec_impl ../Python/bltinmodule.c:1096
    #11 0x70e41ce9c8af in builtin_exec ../Python/clinic/bltinmodule.c.h:586
    #12 0x70e41cd1fbd2 in _PyEval_EvalFrameDefault Python/bytecodes.c:2966
    #13 0x70e41cd82d9d in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #14 0x70e41cd82d9d in object_vacall ../Objects/call.c:850
    #15 0x70e41cd82fe0 in PyObject_CallMethodObjArgs ../Objects/call.c:911
    #16 0x70e41ced8141 in import_find_and_load ../Python/import.c:2779
    #17 0x70e41ced8141 in PyImport_ImportModuleLevelObject ../Python/import.c:2862
    #18 0x70e41cd23a6b in import_name ../Python/ceval.c:2482
    #19 0x70e41cd23a6b in _PyEval_EvalFrameDefault Python/bytecodes.c:2135
    #20 0x70e41cea091e in _PyEval_EvalFrame ../Include/internal/pycore_ceval.h:89
    #21 0x70e41cea091e in _PyEval_Vector ../Python/ceval.c:1683
    #22 0x70e41cea091e in PyEval_EvalCode ../Python/ceval.c:578
    #23 0x70e41ce9c8af in builtin_exec_impl ../Python/bltinmodule.c:1096
    #24 0x70e41ce9c8af in builtin_exec ../Python/clinic/bltinmodule.c.h:586
    #25 0x70e41cd1fbd2 in _PyEval_EvalFrameDefault Python/bytecodes.c:2966
    #26 0x70e41cd82d9d in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #27 0x70e41cd82d9d in object_vacall ../Objects/call.c:850
    #28 0x70e41cd82fe0 in PyObject_CallMethodObjArgs ../Objects/call.c:911
    #29 0x70e41ced8141 in import_find_and_load ../Python/import.c:2779
    #30 0x70e41ced8141 in PyImport_ImportModuleLevelObject ../Python/import.c:2862
    #31 0x70e41ce99c36 in builtin___import___impl ../Python/bltinmodule.c:275
    #32 0x70e41ce99c36 in builtin___import__ ../Python/clinic/bltinmodule.c.h:107
    #33 0x70e41cddfadb in cfunction_vectorcall_FASTCALL_KEYWORDS ../Objects/methodobject.c:438
    #34 0x70e41cd8339b in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #35 0x70e41cd8339b in _PyObject_CallFunctionVa ../Objects/call.c:562
    #36 0x70e41cd835ef in PyObject_CallFunction ../Objects/call.c:584
    #37 0x70e41ced8b1e in PyImport_Import ../Python/import.c:3048
    #38 0x70e41ced8d2f in PyImport_ImportModule ../Python/import.c:2488
    #39 0x70e41cef464c in init_import_site ../Python/pylifecycle.c:2279
    #40 0x70e41cef464c in init_interp_main ../Python/pylifecycle.c:1191
    #41 0x70e41cef5dc0 in new_interpreter ../Python/pylifecycle.c:2110
    #42 0x70e41cef5dc0 in Py_NewInterpreterFromConfig ../Python/pylifecycle.c:2140
    #43 0x5e4ce966b8d6 in pybind11::subinterpreter::create(PyInterpreterConfig const&) /home/user/pybind11/include/pybind11/subinterpreter.h:88
    #44 0x5e4ce966b8d6 in pybind11::subinterpreter::create() /home/user/pybind11/include/pybind11/subinterpreter.h:122
    #45 0x5e4ce966b8d6 in operator() /home/user/pybind11/tests/test_embed/test_subinterpreter.cpp:333
    #46 0x70e41c8ecdb3  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xecdb3) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #47 0x70e41d65ea41 in asan_thread_start ../../../../src/libsanitizer/asan/asan_interceptors.cpp:234
    #48 0x70e41c49caa3 in start_thread nptl/pthread_create.c:447
    #49 0x70e41c529c3b in clone3 ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

0x518000090890 is located 16 bytes inside of 816-byte region [0x518000090880,0x518000090bb0)
allocated by thread T2 here:
    #0 0x70e41d6fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x70e41cde7900 in _PyMem_DebugRawAlloc ../Objects/obmalloc.c:2096
    #2 0x70e41cde7900 in _PyMem_DebugRawMalloc ../Objects/obmalloc.c:2129
    #3 0x70e41cdea30f in _PyObject_Malloc ../Objects/obmalloc.c:1569
    #4 0x70e41cde630d in _PyMem_DebugRawAlloc ../Objects/obmalloc.c:2096
    #5 0x70e41cdca46b in new_keys_object ../Objects/dictobject.c:641
    #6 0x70e41cdcbc81 in dictresize ../Objects/dictobject.c:1449
    #7 0x70e41cdd1b9e in insertion_resize ../Objects/dictobject.c:1194
    #8 0x70e41cdd1b9e in insertdict ../Objects/dictobject.c:1261
    #9 0x70e41cd24ced in _PyEval_EvalFrameDefault Python/bytecodes.c:579
    #10 0x70e41cd82d9d in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #11 0x70e41cd82d9d in object_vacall ../Objects/call.c:850
    #12 0x70e41cd82fe0 in PyObject_CallMethodObjArgs ../Objects/call.c:911
    #13 0x70e41ced8141 in import_find_and_load ../Python/import.c:2779
    #14 0x70e41ced8141 in PyImport_ImportModuleLevelObject ../Python/import.c:2862
    #15 0x70e41cd23a6b in import_name ../Python/ceval.c:2482
    #16 0x70e41cd23a6b in _PyEval_EvalFrameDefault Python/bytecodes.c:2135
    #17 0x70e41cea091e in _PyEval_EvalFrame ../Include/internal/pycore_ceval.h:89
    #18 0x70e41cea091e in _PyEval_Vector ../Python/ceval.c:1683
    #19 0x70e41cea091e in PyEval_EvalCode ../Python/ceval.c:578
    #20 0x70e41ce9c8af in builtin_exec_impl ../Python/bltinmodule.c:1096
    #21 0x70e41ce9c8af in builtin_exec ../Python/clinic/bltinmodule.c.h:586
    #22 0x70e41cd1fbd2 in _PyEval_EvalFrameDefault Python/bytecodes.c:2966
    #23 0x70e41cd82d9d in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #24 0x70e41cd82d9d in object_vacall ../Objects/call.c:850
    #25 0x70e41cd82fe0 in PyObject_CallMethodObjArgs ../Objects/call.c:911
    #26 0x70e41ced8141 in import_find_and_load ../Python/import.c:2779
    #27 0x70e41ced8141 in PyImport_ImportModuleLevelObject ../Python/import.c:2862
    #28 0x70e41cd23a6b in import_name ../Python/ceval.c:2482
    #29 0x70e41cd23a6b in _PyEval_EvalFrameDefault Python/bytecodes.c:2135
    #30 0x70e41cea091e in _PyEval_EvalFrame ../Include/internal/pycore_ceval.h:89
    #31 0x70e41cea091e in _PyEval_Vector ../Python/ceval.c:1683
    #32 0x70e41cea091e in PyEval_EvalCode ../Python/ceval.c:578
    #33 0x70e41ce9c8af in builtin_exec_impl ../Python/bltinmodule.c:1096
    #34 0x70e41ce9c8af in builtin_exec ../Python/clinic/bltinmodule.c.h:586
    #35 0x70e41cddfadb in cfunction_vectorcall_FASTCALL_KEYWORDS ../Objects/methodobject.c:438
    #36 0x70e41cd19deb in _PyEval_EvalFrameDefault Python/bytecodes.c:3254
    #37 0x70e41cd82d9d in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #38 0x70e41cd82d9d in object_vacall ../Objects/call.c:850
    #39 0x70e41cd82fe0 in PyObject_CallMethodObjArgs ../Objects/call.c:911
    #40 0x70e41ced8141 in import_find_and_load ../Python/import.c:2779
    #41 0x70e41ced8141 in PyImport_ImportModuleLevelObject ../Python/import.c:2862
    #42 0x70e41ce99c36 in builtin___import___impl ../Python/bltinmodule.c:275
    #43 0x70e41ce99c36 in builtin___import__ ../Python/clinic/bltinmodule.c.h:107
    #44 0x70e41cddfadb in cfunction_vectorcall_FASTCALL_KEYWORDS ../Objects/methodobject.c:438
    #45 0x70e41cd8339b in _PyObject_VectorcallTstate ../Include/internal/pycore_call.h:92
    #46 0x70e41cd8339b in _PyObject_CallFunctionVa ../Objects/call.c:562
    #47 0x70e41cd835ef in PyObject_CallFunction ../Objects/call.c:584

Thread T2 created by T0 here:
    #0 0x70e41d6f51f9 in pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:245
    #1 0x70e41c8eceb0 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xeceb0) (BuildId: ca77dae775ec87540acd7218fa990c40d1c94ab1)
    #2 0x5e4ce967a296 in thread<C_A_T_C_H_T_E_S_T_6()::<lambda(int)>&, int> /usr/include/c++/13/bits/std_thread.h:164
    #3 0x5e4ce967a296 in C_A_T_C_H_T_E_S_T_6 /home/user/pybind11/tests/test_embed/test_subinterpreter.cpp:392

Suggested changelog entry:

  • Prevent concurrent creation of sub-interpreters as a workaround for stdlib concurrency issues in Python 3.12.

*/
#if PY_VERSION_HEX < 0x030D0000 && defined(Py_MOD_PER_INTERPRETER_GIL_SUPPORTED)
static std::mutex one_at_a_time;
std::lock_guard<std::mutex> guard(one_at_a_time);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could this make us vulnerable to double-locking deadlocks?

Lock 1 = GIL
Lock 2 = this C++ mutex

If Py_NewInterpreterFromConfig releases (and re-acquires) the GIL, we could have a deadlock.

The usual trick is to release the GIL just before acquiring the C++ mutex, then re-acquire the GIL before calling back into the Python C API (Py_NewInterpreterFromConfig in this case).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Py_NewInterpreterFromConfig requires that the main interpreter GIL be held when being called. Internally it releases the main GIL and acquires the new sub-interpreter's GIL and then performs initialization.

The problem appears to be that the initializing isn't thread-safe so with independent GILs it sometimes causes crashes.

I believe it's safe it have a mutex here, because it is only ever acquired in this one place, and the main GIL is acquired first, so the mutex could only ever be locked if the main GIL is already locked. The main GIL is released before this mutex, allowing another thread to potentially get to the lock here and then wait ..... since the function doesn't reacquire the main GIL, it can continue on, return, and release the mutex. Subsequently it does have to reacquire the main GIL, but that's after this mutex has been released.

Since this crosses the boundary of two different GILs, I can't think of any other way to prevent the problem except with another lock. The only other option would be for us to leave it broken and just document that this is a big unstable on 3.12 (and also fix the unit test to not exercise this behavior).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can't think of any other way to prevent the problem except with another lock. The only other option would be for us to leave it broken

The frequent CI failures are pretty distracting. Thanks for the explanation. Let's merge this and see if we actually get any deadlocks.

*/
#if PY_VERSION_HEX < 0x030D0000 && defined(Py_MOD_PER_INTERPRETER_GIL_SUPPORTED)
static std::mutex one_at_a_time;
std::lock_guard<std::mutex> guard(one_at_a_time);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I can't think of any other way to prevent the problem except with another lock. The only other option would be for us to leave it broken

The frequent CI failures are pretty distracting. Thanks for the explanation. Let's merge this and see if we actually get any deadlocks.

@rwgk
Copy link
Collaborator

rwgk commented Jul 31, 2025

I'm ignoring the unrelated CI flake:

CI / 🐍 (macos-13, 3.13t, -DCMAKE_CXX_STANDARD=11) / 🧪 (pull_request)

@rwgk rwgk merged commit 9af8adb into pybind:master Jul 31, 2025
81 of 82 checks passed
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Jul 31, 2025
@henryiii henryiii changed the title Subinterpreter creation concurrency issues in 3.12 fix: subinterpreter creation concurrency issues in 3.12 Aug 21, 2025
@henryiii henryiii removed the needs changelog Possibly needs a changelog entry label Aug 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants