Python PyGILState_ {Обеспечение / выпуск} вызывает segfault при возврате на C ++ из кода Python

ОБНОВЛЕНИЕ Ну, похоже, что добавление PyEval_InitThreads () перед вызовом PyGILState_Ensure () делает трюк. В своей спешке, чтобы разобраться в деталях, я неправильно приписал свою «зависанию» PyEval_InitThreads ().

Однако, прочитав некоторую документацию на Python, мне интересно, правильно ли это решение.

Небезопасно вызывать эту функцию, когда неизвестно, какой поток (если есть) в настоящее время имеет глобальную блокировку интерпретатора.


Прежде всего, я работаю над некоторым модифицированным кодом GNU Radio, в частности модифицированным блоком gr_bin_statistics_f. Теперь есть отчет об ошибке (хотя и старый), который в значительной степени описывает мою точную ситуацию.

http://gnuradio.org/redmine/issues/show/199

Теперь, usrp_spectrum_sense.py, который упоминается в отчете об ошибке, вызывает gr_bin_statistics_f (C ++), который затем периодически перезаписывает Python, чтобы перенастроить USRP (радио).

Вот что происходит, когда вызывается код Python:

PyGILState_STATE d_gstate; d_gstate = PyGILState_Ensure(); // call python code PyGILState_Release(d_gstate); 

Итак, как только мы вернемся из кода Python, возникает ошибка сегментации, когда вызывается PyGILState_Release (d_gstate). Хотя существуют различия между моим кодом и оригиналом gr_bin_statistics_f, похоже, что это не связано с удаленностью.

Я прочитал, что вызов PyEval_InitThreads () до того, как PyGILState_Ensure () решил проблему для некоторых людей, но это просто заставляет мою программу зависать.

Может ли кто-нибудь пролить свет на это для меня? Или просто отправить сообщение в список рассылки GNU?

Использование Python2.7 на Fedora 14 x86_64.

Вот обратная линия GDB:

 (gdb) c Continuing. [New Thread 0x7fabd3a8d700 (LWP 23969)] [New Thread 0x7fabd328c700 (LWP 23970)] [New Thread 0x7fabd2a8b700 (LWP 23971)] [New Thread 0x7fabd228a700 (LWP 23972)] [New Thread 0x7fabd1a89700 (LWP 23973)] [New Thread 0x7fabd1288700 (LWP 23974)] [New Thread 0x7fabd0a87700 (LWP 23975)] [New Thread 0x7fabbbfff700 (LWP 23976)] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x7fabbbfff700 (LWP 23976)] 0x00000036b3e0db00 in sem_post () from /lib64/libpthread.so.0 (gdb) bt #0 0x00000036b3e0db00 in sem_post () from /lib64/libpthread.so.0 #1 0x00000036c1317679 in PyThread_release_lock () from /usr/lib64/libpython2.7.so.1.0 #2 0x00007fabd6159c1f in ~ensure_py_gil_state (this=0x2dc6fc0, x=887000000) at gnuradio_swig_py_general.cc:5593 #3 gr_py_feval_dd::calleval (this=0x2dc6fc0, x=887000000) at gnuradio_swig_py_general.cc:5605 #4 0x00007fabd77c4b6e in gr_noise_level_f::tune_window (this=0x2db3ca0, target_freq=) at gr_noise_level_f.cc:97 #5 0x00007fabd77c554b in gr_noise_level_f::work (this=0x2db3ca0, noutput_items=7, input_items=, output_items=) at gr_noise_level_f.cc:115 #6 0x00007fabd7860714 in gr_sync_block::general_work (this=0x2db3ca0, noutput_items=, ninput_items=, input_items=, output_items=) at gr_sync_block.cc:64 #7 0x00007fabd7846ce4 in gr_block_executor::run_one_iteration (this=0x7fabbbffed90) at gr_block_executor.cc:299 #8 0x00007fabd7864332 in gr_tpb_thread_body::gr_tpb_thread_body (this=0x7fabbbffed90, block=...) at gr_tpb_thread_body.cc:49 #9 0x00007fabd785cce7 in operator() (function_obj_ptr=...) at gr_scheduler_tpb.cc:42 #10 operator() (function_obj_ptr=...) at /home/tja/Research/energy/detector/gnuradio-3.3.0/gruel/src/include/gruel/thread_body_wrapper.h:49 #11 boost::detail::function::void_function_obj_invoker0, void>::invoke (function_obj_ptr=...) at /usr/include/boost/function/function_template.hpp:153 ---Type to continue, or q to quit--- #12 0x00007fabd74914ef in operator() (this=) at /usr/include/boost/function/function_template.hpp:1013 #13 boost::detail::thread_data >::run (this=) at /usr/include/boost/thread/detail/thread.hpp:61 #14 0x00007fabd725ca55 in thread_proxy () from /usr/lib64/libboost_thread-mt.so.1.44.0 #15 0x00000036b3e06d5b in start_thread () from /lib64/libpthread.so.0 #16 0x00000036b3ae4a7d in clone () from /lib64/libc.so.6 (gdb) 

Спасибо, что посмотрели!

  • PySide: Segfault (?) При использовании QItemSelectionModel с QListView
  • Разреженная матричная нарезка с использованием списка int
  • ошибка сегментации в вычислении pi (python)
  • Функция libVLC media_player_new () вызывает ошибку сегментации
  • Почему существует предел длины для eval python?
  • Ошибка сегментации с opencv, в python на малине
  • Ошибка сегментации при перенаправлении sys.stdout на виджет Tkinter.Text
  • Случайное применение ошибки сегментации в функциях расширения python в c ++
  • 2 Solutions collect form web for “Python PyGILState_ {Обеспечение / выпуск} вызывает segfault при возврате на C ++ из кода Python”

    Python ожидает, что основной поток инициализации будет выполняться основным потоком, прежде чем что-либо попытается перезвонить из подпотока.

    Если основной поток – это приложение, которое встраивает Python, тогда он должен вызывать PyEval_InitThreads() сразу после вызова Py_Initialize() .

    Если основной поток – это сам интерпретатор Python (как это здесь имеет место), то модуль, использующий многопоточный модуль расширения, должен сначала включить «импортную резьбу», чтобы убедиться, что PyEval_InitThreads() вызывается правильно до того, как PyEval_InitThreads() любые подпотоки ,

    Я столкнулся с этой точной проблемой. Документация для чего-либо, связанного с потоками в CPython, к сожалению, в лучшем случае неоднородна.

    По сути, вам нужно сделать следующее:

    В вашем основном потоке, PyEval_InitThreads() все другие потоки, вам нужно вызвать PyEval_InitThreads() . Хорошее место для этого – сразу после вызова PyInitialize() .

    Теперь PyEval_InitThreads() не только инициализирует состояние потока интерпретатора Python, но также неявно приобретает глобальную блокировку интерпретатора. Это означает, что вам нужно освободить блокировку, прежде чем вы PyGILEnsure_State() в каком-то другом потоке, иначе ваша программа зависает. Вы можете сделать это с помощью функции PyEval_ReleaseLock() .

    Итак, в основном, в вашем основном потоке, прежде чем запускать какие-либо другие потоки, вы хотите сказать:

     PyInitialize(); PyEval_InitThreads(); PyEval_ReleaseLock(); 

    Затем, в любом дополнительном потоке, в любое время, когда вы используете API Python, вам нужно сказать:

     PyGILState_STATE gstate; gstate = PyGILState_Ensure(); /* ... some code that does things with Python ... */ PyGILState_Release(gstate); 
    Python - лучший язык программирования в мире.