Skip to content

Commit f0e6ac2

Browse files
committed
This test created a subinterpreter when PYBIND11_SUBINTERPRETER_SUPPORT was off
So the fix is really this test should not be run in these older versions at all. The hang was a GIL issue between the subinterpreters during pybind11::exception::what().
1 parent ca5ea1e commit f0e6ac2

File tree

2 files changed

+11
-16
lines changed

2 files changed

+11
-16
lines changed

include/pybind11/pybind11.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1484,7 +1484,7 @@ class module_ : public object {
14841484
using slots_array = std::array<PyModuleDef_Slot, 4>;
14851485

14861486
/** \rst
1487-
Initialized a module def for use with multi-phase module initialization.
1487+
Initialize a module def for use with multi-phase module initialization.
14881488
14891489
``def`` should point to a statically allocated module_def.
14901490
``slots`` must already contain a Py_mod_exec or Py_mod_create slot and will be filled with

tests/test_embed/test_interpreter.cpp

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
339340
TEST_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)
401402
TEST_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();
@@ -527,13 +528,7 @@ TEST_CASE("Per-Subinterpreter GIL") {
527528
T_REQUIRE(caught);
528529

529530
// widget_module did provide the per_interpreter_gil tag, so it this does not throw
530-
try {
531-
py::module_::import("widget_module");
532-
caught = false;
533-
} catch (pybind11::error_already_set &) {
534-
caught = true;
535-
}
536-
T_REQUIRE(!caught);
531+
py::module_::import("widget_module");
537532

538533
T_REQUIRE(!py::hasattr(py::module_::import("external_module"), "multi_interp"));
539534
py::module_::import("external_module").attr("multi_interp") = std::to_string(num);
@@ -557,8 +552,8 @@ TEST_CASE("Per-Subinterpreter GIL") {
557552

558553
Py_EndInterpreter(sub);
559554

560-
PyThreadState_Swap(
561-
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);
562557
};
563558

564559
std::thread t1(thread_main, 1);

0 commit comments

Comments
 (0)