Python сценарий зависает после SIGINT "завершение вызова без активного исключения, когда" - PullRequest
0 голосов
/ 08 мая 2020

У меня есть приложение python, которое собирает данные с датчика. Драйвер для датчика имеет закрытый исходный код, и я написал обертку вокруг него, чтобы упростить его использование. Все приложение работает на Linux. Программа имеет следующий поток.

  1. Python вызов в настройку драйвера. Это запускает один std :: thread, который я контролирую, который опрашивает датчик и помещает полученные данные в std :: queue. Он также вызывает код запуска драйвера с закрытым исходным кодом, который запускает несколько потоков.
  2. Python основной поток начинает цикл, выбирая вещи из очереди данных от датчика через вызов драйвера C ++ (driver.getData). Получив данные, он выполняет некоторую буферизацию, и после агрегирования фиксированного числа выборок они записываются в файл.
  3. В конце концов я хочу, чтобы программа остановилась, поэтому я нажимаю ctrl + c, чтобы отправить SIGINT процесса. У меня есть обработчик, зарегистрированный с помощью функции python signal.signal, которая улавливает сигнал, изменяет значение логического значения и возвращает. Я знаю, что обработчик выполняется, потому что у меня есть оператор печати в начале обработчика.
  4. На этом этапе я ожидал, что основной поток python перестанет зацикливаться на своем while l oop (поскольку условие он проверяет, что обработчик теперь установил значение False) и запустите мой код очистки.

Шаг 4 происходит только в том случае, если поток C ++ не запущен (никогда не запускался или был остановлен). Если поток запущен, и я извлекаю данные из очереди данных датчика, я получаю «завершение вызова без активного исключения» , и мое приложение зависает. Другие вопросы, в которых упоминается это сообщение, указывают на то, что причиной сообщения не было присоединения к потокам перед выходом, но мой код никогда не попадает в мой оператор соединения в моем коде выключения.

Если бы мне пришлось угадывать, это похоже на одно из потоки драйвера или мой поток C ++ завершаются, как только выдается SIGINT, в результате чего основной поток python зависает в ожидании помещения последнего фрагмента данных в очередь (прямо сейчас я отбираю датчик на очень низком уровне ставка). Но я могу ошибаться в этом.

Есть ли причина, по которой сигнал SIGINT может останавливать один из других потоков? Если это так, могу ли я предотвратить это?

Спасибо!

Примерный набросок моего кода.

основное python приложение

import driver # this wraps a bunch of ctypes calls

def sigint_handler(sig,frame):
    print('handling SIGINT signal')
    global isRun
    isRun = false

global isRun
isRun = True

signal.signal(SIGINT,sigint_handler)
driver.setupDriver()

while isRun:
  data = driver.getData() 
  logger.log(data)

print('cleaning up')
driver.stopDriver() #this should stop the c++ threads
logger.stop()

мой слой интерфейса драйвера c ++


std::queue<data_t> sensorDataQ()
std::mutex dataq_mutex()
std::thread worker
bool isRun = True;

void workerWork()
{
   while(isRun)
   {
   auto data = getData_sensor_primary_driver();

   {
       std::lock_guard(dataq_mutex)
       sensorDataQ.push(data)
   }
   }

}

extern "C" data_t getData()
{
    while(sensorDataQ.empty())
   {
      std::this_thread::sleep_for(50) //sleep for 50 miliseconds until we get some data
   }
   {
       std::lock_guard(dataq_mutex)
       sensorDataQ.push(data)
   }


}

extern "C" startDriver()
{
    start_sensor_primary_driver() // this appears to start 4 threads according to GDB
    worker = std::thread(workerWork)
    worker.start()
}

extern "C" stopDriver()
{
    isRun = false;
    worker.join()
    cleanup_primary_driver()
}

1 Ответ

0 голосов
/ 08 мая 2020

После некоторых дополнительных поисков похоже, что базовый драйвер регистрирует обработчик сигнала SIGINT и вызывает exit, прежде чем я смогу очистить свои потоки.

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