diff --git a/python/kwiver/sprokit/adapters/embedded_pipeline.cxx b/python/kwiver/sprokit/adapters/embedded_pipeline.cxx index 9d46f05940..055129daa6 100644 --- a/python/kwiver/sprokit/adapters/embedded_pipeline.cxx +++ b/python/kwiver/sprokit/adapters/embedded_pipeline.cxx @@ -55,17 +55,26 @@ PYBIND11_MODULE(embedded_pipeline, m) ksp::embedded_pipeline_trampoline> ep(m, "EmbeddedPipeline"); ep.def(init<>()) .def("build_pipeline", &ksp::build_pipeline, + call_guard(), arg("desc_file"), arg("def_dir") = "") - .def("send", &kwiver::embedded_pipeline::send) - .def("send_end_of_input", &kwiver::embedded_pipeline::send_end_of_input) - .def("receive", &kwiver::embedded_pipeline::receive) - .def("full", &kwiver::embedded_pipeline::full) - .def("empty", &kwiver::embedded_pipeline::empty) + .def("send", &kwiver::embedded_pipeline::send, + call_guard()) + .def("send_end_of_input", &kwiver::embedded_pipeline::send_end_of_input, + call_guard()) + .def("receive", &kwiver::embedded_pipeline::receive, + call_guard()) + .def("full", &kwiver::embedded_pipeline::full, + call_guard()) + .def("empty", &kwiver::embedded_pipeline::empty, + call_guard()) .def("at_end", &kwiver::embedded_pipeline::at_end) - .def("start", &kwiver::embedded_pipeline::start) - .def("wait", &kwiver::embedded_pipeline::wait) - .def("stop", &kwiver::embedded_pipeline::stop) + .def("start", &kwiver::embedded_pipeline::start, + call_guard()) + .def("wait", &kwiver::embedded_pipeline::wait, + call_guard()) + .def("stop", &kwiver::embedded_pipeline::stop, + call_guard()) .def("input_port_names", &kwiver::embedded_pipeline::input_port_names) .def("output_port_names", &kwiver::embedded_pipeline::output_port_names) .def("input_adapter_connected", @@ -73,11 +82,14 @@ PYBIND11_MODULE(embedded_pipeline, m) .def("output_adapter_connected", &ksp::wrap_embedded_pipeline::output_adapter_connected) .def("connect_input_adapter", - static_cast(&ksp::wrap_embedded_pipeline::connect_input_adapter)) + static_cast(&ksp::wrap_embedded_pipeline::connect_input_adapter), + call_guard()) .def("connect_output_adapter", - static_cast(&ksp::wrap_embedded_pipeline::connect_output_adapter)) + static_cast(&ksp::wrap_embedded_pipeline::connect_output_adapter), + call_guard()) .def("update_config", - static_cast(&ksp::wrap_embedded_pipeline::update_config)) + static_cast(&ksp::wrap_embedded_pipeline::update_config), + call_guard()) ; ep.doc() = R"( Python bindings for kwiver::embedded_pipeline diff --git a/python/kwiver/vital/modules/module_helpers.cxx b/python/kwiver/vital/modules/module_helpers.cxx index 08f4364ffd..61d42be578 100644 --- a/python/kwiver/vital/modules/module_helpers.cxx +++ b/python/kwiver/vital/modules/module_helpers.cxx @@ -28,6 +28,8 @@ namespace py = pybind11; */ void check_and_initialize_python_interpretor() { + static bool initialized = false; + // Check if a python interpreter already exists so we don't clobber sys.argv // (e.g. if sprokit is initialized from python) if (!Py_IsInitialized()) @@ -38,16 +40,20 @@ void check_and_initialize_python_interpretor() // Set Python interpeter attribute: sys.argv = [] // parameters are: (argc, argv, updatepath) PySys_SetArgvEx(0, NULL, 0); - } - if (!PyEval_ThreadsInitialized()) - { + // In Python 3.7+, threads are always initialized after Py_Initialize(), + // so PyEval_ThreadsInitialized() always returns true. We need to + // initialize pybind11 internals and release the GIL ourselves. + if (!initialized) { - // Let pybind11 initialize threads and set up its internal data structures - pybind11::detail::get_internals(); + initialized = true; + { + // Let pybind11 initialize threads and set up its internal data structures + pybind11::detail::get_internals(); + } + // Release the GIL so other threads can acquire it + PyEval_SaveThread(); } - // Release the GIL - PyEval_SaveThread(); } }