Вызов Py_Finalize () из C - PullRequest
       11

Вызов Py_Finalize () из C

9 голосов
/ 15 сентября 2009

Это продолжение до Вызов Python из C ++

При запуске программы я вызываю следующую функцию для инициализации интерпретатора:

void initPython(){
    PyEval_InitThreads();
    Py_Initialize();
    PyEval_ReleaseLock();
}

Каждый поток создает свою собственную структуру данных и получает блокировку с помощью:

PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
//call python API, process results
PyGILState_Release(gstate);

Скорее прямо, как только вы поймете GIL, но проблема в том, что я получаю segfault при вызове Py_Finalize ().

void exitPython(){
    PyEval_AcquireLock();
    Py_Finalize();
}

Ссылка довольно сомнительна в отношении Py_Finalize () (или, может быть, я просто читаю это неправильно), и я не уверен, может ли PyEval_AcquireLock () получить блокировку, если есть активные потоки, и что произойдет, если там являются активными потоками, когда вызывается Py_Finalize ().

В любом случае, я получаю сегфо, даже если я уверен, что все потоки закончили свою работу, но только если был создан хотя бы один. Например. вызов initPython (), сопровождаемый exitPython (), не создает ошибки.

Я мог бы просто игнорировать проблему и надеяться, что ОС знает, что она делает, но я бы предпочел, чтобы я мог выяснить, что происходит ..

Ответы [ 3 ]

7 голосов
/ 16 сентября 2009

Да, весь раздел довольно сомнительный, но я думаю, что я ошибся.

Мне нужно сохранить PyThreadState при инициализации интерпретатора и поменять это состояние обратно, когда я его завершу (не знаю, зачем мне нужен конкретный ThreadState для вызова Finalize - не должно ли работать каждое государство?) *

В любом случае пример, если другие люди получили такую ​​же проблему:

PyThreadState *mainstate;

void initPython(){
    PyEval_InitThreads();
    Py_Initialize();
    mainstate = PyThreadState_Swap(NULL);
    PyEval_ReleaseLock();
}

void exitPython(){
    PyEval_AcquireLock();
    PyThreadState_Swap(mainstate);
    Py_Finalize();
}

Единственная проблема в том, что я могу получить блокировку, как и любой другой поток, даже если все еще работают потоки. В API не упоминается, что происходит при вызове Finalize (), когда другие потоки все еще работают. Звучит как идеальный пример состояния гонки ..

1 голос
/ 22 января 2015

У меня также возникает аналогичная проблема при запуске скриптов, содержащих pyxhook, из разных потоков через встроенный интерпретатор.

Нет проблем, если один скрипт выполняется одновременно. Хук освобождается правильно, но если два или более сценария выполняются параллельно, перехват не останавливается. Хотя мои сценарии вернулись правильно и cancel() из pyxhook также вернулось правильно, я думаю, что некоторые потоки все еще работают, связанные с xlib. Эту проблему pyxhook я решил, сохранив глобальный флаг, чтобы следить за тем, запущен ли pyxhook, и не переинициализировать pyxhook из каждого потока.

Теперь относительно Py_Finalize(), если pyxhook повторно инициализируется в каждом потоке:

если я не вызову PyEval_AcquireLock() и PyThreadState_Swap() до вызова Py_Finalize(), он завершается в Linux, но не в Win32. В Win32 есть проблема, если я не иду через PyEval_AcquireLock() и PyThreadState_Swap().

В настоящее время временное решение для меня заключается в том, чтобы по-разному завершаться в двух разных ОС.

1 голос
/ 16 сентября 2009

Вы пытались комментировать всю «работу», проделанную в ваших темах? Замените это занятым циклом или сном или чем-то. Это поможет точно определить, является ли это ваш код инициализации / завершения работы или что-то, что вы на самом деле делаете с Python между ними. Возможно, вы не настраиваете потоки должным образом - в C API имеется множество специфичных для потока функций, и я не уверен, какие из них вам необходимы для обеспечения правильной работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...