@@ -55,7 +55,7 @@ class test_override_cache_helper_trampoline : public test_override_cache_helper
5555 int func () override { PYBIND11_OVERRIDE (int , test_override_cache_helper, func); }
5656};
5757
58- PYBIND11_EMBEDDED_MODULE (widget_module, m) {
58+ PYBIND11_EMBEDDED_MODULE (widget_module, m, py::multiple_interpreters::per_interpreter_gil() ) {
5959 py::class_<Widget, PyWidget>(m, " Widget" )
6060 .def (py::init<std::string>())
6161 .def_property_readonly (" the_message" , &Widget::the_message);
@@ -336,6 +336,7 @@ TEST_CASE("Restart the interpreter") {
336336 REQUIRE (py_widget.attr (" the_message" ).cast <std::string>() == " Hello after restart" );
337337}
338338
339+ #if defined(PYBIND11_SUBINTERPRETER_SUPPORT)
339340TEST_CASE (" Subinterpreter" ) {
340341 py::module_::import (" external_module" ); // in the main interpreter
341342
@@ -347,6 +348,10 @@ TEST_CASE("Subinterpreter") {
347348
348349 REQUIRE (m.attr (" add" )(1 , 2 ).cast <int >() == 3 );
349350 }
351+
352+ auto main_int
353+ = py::module_::import (" external_module" ).attr (" internals_at" )().cast <uintptr_t >();
354+
350355 REQUIRE (has_state_dict_internals_obj ());
351356 REQUIRE (has_pybind11_internals_static ());
352357
@@ -359,7 +364,6 @@ TEST_CASE("Subinterpreter") {
359364 // Subinterpreters get their own copy of builtins.
360365 REQUIRE_FALSE (has_state_dict_internals_obj ());
361366
362- #if defined(PYBIND11_SUBINTERPRETER_SUPPORT) && PY_VERSION_HEX >= 0x030C0000
363367 // internals hasn't been populated yet, but will be different for the subinterpreter
364368 REQUIRE_FALSE (has_pybind11_internals_static ());
365369
@@ -369,14 +373,12 @@ TEST_CASE("Subinterpreter") {
369373 py::detail::get_internals ();
370374 REQUIRE (has_pybind11_internals_static ());
371375 REQUIRE (get_details_as_uintptr () == ext_int);
372- #else
373- // This static is still defined
374- REQUIRE (has_pybind11_internals_static ());
375- #endif
376+ REQUIRE (main_int != ext_int);
376377
377378 // Modules tags should be gone.
378379 REQUIRE_FALSE (py::hasattr (py::module_::import (" __main__" ), " tag" ));
379380 {
381+ REQUIRE_NOTHROW (py::module_::import (" widget_module" ));
380382 auto m = py::module_::import (" widget_module" );
381383 REQUIRE_FALSE (py::hasattr (m, " extension_module_tag" ));
382384
@@ -397,7 +399,6 @@ TEST_CASE("Subinterpreter") {
397399 REQUIRE (has_state_dict_internals_obj ());
398400}
399401
400- #if defined(PYBIND11_SUBINTERPRETER_SUPPORT)
401402TEST_CASE (" Multiple Subinterpreters" ) {
402403 // Make sure the module is in the main interpreter and save its pointer
403404 auto *main_ext = py::module_::import (" external_module" ).ptr ();
@@ -512,10 +513,11 @@ TEST_CASE("Per-Subinterpreter GIL") {
512513
513514 // we have switched to the new interpreter and released the main gil
514515
515- // widget_module did not provide the mod_per_interpreter_gil tag, so it cannot be imported
516+ // trampoline_module did not provide the per_interpreter_gil tag, so it cannot be
517+ // imported
516518 bool caught = false ;
517519 try {
518- py::module_::import (" widget_module " );
520+ py::module_::import (" trampoline_module " );
519521 } catch (pybind11::error_already_set &pe) {
520522 T_REQUIRE (pe.matches (PyExc_ImportError));
521523 std::string msg (pe.what ());
@@ -525,6 +527,9 @@ TEST_CASE("Per-Subinterpreter GIL") {
525527 }
526528 T_REQUIRE (caught);
527529
530+ // widget_module did provide the per_interpreter_gil tag, so it this does not throw
531+ py::module_::import (" widget_module" );
532+
528533 T_REQUIRE (!py::hasattr (py::module_::import (" external_module" ), " multi_interp" ));
529534 py::module_::import (" external_module" ).attr (" multi_interp" ) = std::to_string (num);
530535
@@ -547,8 +552,8 @@ TEST_CASE("Per-Subinterpreter GIL") {
547552
548553 Py_EndInterpreter (sub);
549554
550- PyThreadState_Swap (
551- main_tstate); // switch back so the scoped_acquire can release the GIL properly
555+ // switch back so the scoped_acquire can release the GIL properly
556+ PyThreadState_Swap ( main_tstate);
552557 };
553558
554559 std::thread t1 (thread_main, 1 );
@@ -622,12 +627,26 @@ TEST_CASE("Threads") {
622627
623628 {
624629 py::gil_scoped_release gil_release{};
630+ #if defined(Py_GIL_DISABLED) && PY_VERSION_HEX < 0x030E0000
631+ std::mutex mutex;
632+ #endif
625633
626634 auto threads = std::vector<std::thread>();
627635 for (auto i = 0 ; i < num_threads; ++i) {
628636 threads.emplace_back ([&]() {
629637 py::gil_scoped_acquire gil{};
638+ #ifdef Py_GIL_DISABLED
639+ # if PY_VERSION_HEX < 0x030E0000
640+ std::lock_guard<std::mutex> lock (mutex);
641+ locals[" count" ] = locals[" count" ].cast <int >() + 1 ;
642+ # else
643+ Py_BEGIN_CRITICAL_SECTION (locals.ptr ());
630644 locals[" count" ] = locals[" count" ].cast <int >() + 1 ;
645+ Py_END_CRITICAL_SECTION ();
646+ # endif
647+ #else
648+ locals[" count" ] = locals[" count" ].cast <int >() + 1 ;
649+ #endif
631650 });
632651 }
633652
0 commit comments