В моем многопоточном приложении происходит сбой при вызове PyImport_ImportModule("my_module")
.
БТ будет размещен внизу.
Некоторый фон:
- Мое приложение создает несколько экземпляров многих производных классов C ++ и запускает функцию
Run()
базового класса, которая использует виртуальный метод для определения того, что делать.
- Один производный класс использует класс Python,
Grasp_Behavior
(класс) в grasp_behavior
(модуль)
- После подробного прочтения я использовал Python API для достижения (2) (выдержки ниже)
- Я генерирую 2 экземпляра указанного класса и запускаю их "параллельно" (python interpr на самом деле не работает параллельно)
- Я пытаюсь сгенерировать другой экземпляр указанного класса, segfault на
PyImport_ImportModule
Я думаю, что, возможно, я не могу дважды импортировать модуль в одном и том же интерпретаторе. Но я не могу понять, как это проверить. Я предполагаю, что мне нужно посмотреть, есть ли grasp_behavior
в словаре, но я не знаю, какой именно, возможно, я получаю словарь модуля __main__
?
Но я могу ошибаться, любой совет был бы невероятно полезен!
В конструкторе:
//Check if Python is Initialized, otherwise initialize it
if(!Py_IsInitialized())
{
std::cout << "[GraspBehavior] InitPython: Initializing the Python Interpreter" << std::endl;
Py_Initialize();
PyEval_InitThreads(); //Initialize Python thread ability
PyEval_ReleaseLock(); //Release the implicit lock on the Python GIL
}
// --- Handle Imports ----
PyObject * pModule = PyImport_ImportModule("grasp_behavior");
if(pModule == NULL)
{
std::cout << "[GraspBehavior] InitPython: Unable to import grasp_behavior module: ";
PyErr_Print();
}
// --- Get our Class Pointer From the Module ...
PyObject * pClass = PyObject_GetAttrString(pModule, "Grasp_Behavior");
if(pClass == NULL)
{
std::cout << "[GraspBehavior] InitPython: Unable to get Class from Module: ";
PyErr_Print();
}
Py_DECREF(pModule); //clean up, this is a new reference
behavior_instance_ = PyObject_Call(pClass, pArguments_Tuple, pArguments_Dict);
if(behavior_instance_ == NULL)
{
std::cout << "[GraspBehavior] InitPython: Couldn't generate instance: ";
PyErr_Print();
}
Py_DECREF(pArguments_Tuple);
Py_DECREF(pArguments_Dict);
Py_DECREF(pClass);
Здесь обратите внимание, что я инициализирую интерпретатор Python, только если он не был инициализирован. Я предполагаю, что он инициализируется для всего процесса.
В методе Run()
(запускается из потока поддержки):
std::cout << "[GraspBehavior] PerformBehavior: Acquiring Python GIL Lock ..." << std::endl;
PyGILState_STATE py_gilstate;
py_gilstate = PyGILState_Ensure();
/* ---- Perform Behavior Below ----- */
std::vector<std::pair<double, double> > desired_body_offsets;
//desired_body_offsets.push_back( std::pair<double, double>(0.6, 0));
PyObject * base_positions = GetTrialBasePositions(my_env_, desired_body_offsets);
PyObject * grasps = EvaluateBasePositions(my_env_, base_positions);
//Did we get any grasps? What do we do with them? [TODO]
if(grasps != NULL)
{
std::cout << grasps->ob_type->tp_name << std::endl;
std::cout << "Number of grasps: " << PyList_Size(grasps) << std::endl;
successful_ = true;
}
/* --------------------------------- */
std::cout << "[GraspBehavior] PerformBehavior: Releasing Python GIL Lock ..." << std::endl;
PyGILState_Release(py_gilstate);
Здесь я пошел с PyGILState
замком. Некоторое время я читал, и некоторые статьи, на которые ссылаются многие, используют более старый стиль блокировки в Python ... возможно, мне придется изменить это.
Backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x00007fffee9c4330 in ?? () from /usr/lib/libpython2.6.so.1.0
(gdb) bt
#0 0x00007fffee9c4330 in ?? () from /usr/lib/libpython2.6.so.1.0
#1 0x00007fffee99ff09 in PyEval_GetGlobals ()
from /usr/lib/libpython2.6.so.1.0
#2 0x00007fffee9bd993 in PyImport_Import () from /usr/lib/libpython2.6.so.1.0
#3 0x00007fffee9bdbec in PyImport_ImportModule ()
from /usr/lib/libpython2.6.so.1.0
#4 0x000000000042d6f0 in GraspBehavior::InitPython (this=0x7948690)
at grasp_behavior.cpp:241