Я разработал расширение Python, используя C++. Единственная функция этого модуля примерно такая:
static PyObject *TestModule_API1(PyObject *self, PyObject *args)
{
PyThreadState *_save;
_save = PyEval_SaveThread();
try
{
DoComputation1();
PyEval_RestoreThread(_save);
}
catch (const std::exception & e)
{
PyObject * py_exception = PyErr_NewException((char*)"pyhms.error", nullptr, nullptr);
PyErr_SetString(py_exception, e.what());
PyEval_RestoreThread(_save);
return nullptr;
}
Py_RETURN_NONE;
}
Всякий раз, когда я вызываю этот метод с двумя потоками Python, если метод DoComputation1()
выдает исключение, приложение аварийно завершает работу. Даже помещение всего блока try внутрь std::mutex (блокировка в начале и разблокировка в конце блока) не решает проблему. Какова основная причина этой проблемы и как ее исправить?
Я разрабатываю Windows 10, используя Visual Studio 2013 и Python 2.7.
Редактировать 1:
Если я перенесу строку PyEval_RestoreThread(_save);
(в блоке catch) в начало блока catch, сбоев не произойдет. Означает ли это, что во время выпуска GIL я не должен вызывать какой-либо Python API?
Редактировать 2:
Мне также нужно защитить мой метод API1 от параллельных потоков с помощью мьютекса. Должен ли я заблокировать свой мьютекс перед тем, как освободить GIL после этого? Есть ли случай, который может привести к тупику?