From 6e3f91dc6b79475a411b79b1880c45f2a99bdfa5 Mon Sep 17 00:00:00 2001 From: Ben Frederickson Date: Fri, 16 Feb 2018 10:15:55 -0800 Subject: [PATCH] Fix deadlock in child threads launched from python Pybind11 seems to have an issue in gil_scoped_acquire when being called from child threads created from python. This resulted in a deadlock here: https://github.com/searchivarius/nmslib/issues/291 A simple workaround is to use the PyGILState_Ensure from the python c-api directly instead. --- python_bindings/nmslib.cc | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/python_bindings/nmslib.cc b/python_bindings/nmslib.cc index 6bc86ca..764de97 100644 --- a/python_bindings/nmslib.cc +++ b/python_bindings/nmslib.cc @@ -74,12 +74,12 @@ struct IndexWrapper { loadParams(space_params))) { auto vectSpacePtr = dynamic_cast*>(space.get()); if (data_type == DATATYPE_DENSE_VECTOR && vectSpacePtr == nullptr) { - throw std::invalid_argument("The space type " + space_type + + throw std::invalid_argument("The space type " + space_type + " is not compatible with the type DENSE_VECTOR, only dense vector spaces are allowed!"); } auto vectSiftPtr = dynamic_cast(space.get()); if (data_type == DATATYPE_DENSE_UINT8_VECTOR && vectSiftPtr == nullptr) { - throw std::invalid_argument("The space type " + space_type + + throw std::invalid_argument("The space type " + space_type + " is not compatible with the type DENSE_UINT8_VECTOR!"); } } @@ -361,6 +361,20 @@ struct IndexWrapper { ObjectVector data; }; +// pybind11::gil_scoped_acquire can deadlock when acquiring the GIL on threads +// created from python (https://github.com/searchivarius/nmslib/issues/291) +// This might be fixed in a future version of pybind11 (https://github.com/pybind/pybind11/pull/1211) +// but until then, lets fall back to the python c-api to fix. +struct AcquireGIL { + PyGILState_STATE state; + AcquireGIL() + : state(PyGILState_Ensure()) { + } + ~AcquireGIL() { + PyGILState_Release(state); + } +}; + class PythonLogger : public Logger { public: @@ -374,7 +388,7 @@ class PythonLogger int line, const char * function, const std::string & message) { - py::gil_scoped_acquire l; + AcquireGIL l; switch(severity) { case LIB_DEBUG: inner.attr("debug")(message);