У меня есть приложение python, которое собирает данные с датчика. Драйвер для датчика имеет закрытый исходный код, и я написал обертку вокруг него, чтобы упростить его использование. Все приложение работает на Linux. Программа имеет следующий поток.
- Python вызов в настройку драйвера. Это запускает один std :: thread, который я контролирую, который опрашивает датчик и помещает полученные данные в std :: queue. Он также вызывает код запуска драйвера с закрытым исходным кодом, который запускает несколько потоков.
- Python основной поток начинает цикл, выбирая вещи из очереди данных от датчика через вызов драйвера C ++ (driver.getData). Получив данные, он выполняет некоторую буферизацию, и после агрегирования фиксированного числа выборок они записываются в файл.
- В конце концов я хочу, чтобы программа остановилась, поэтому я нажимаю ctrl + c, чтобы отправить SIGINT процесса. У меня есть обработчик, зарегистрированный с помощью функции python signal.signal, которая улавливает сигнал, изменяет значение логического значения и возвращает. Я знаю, что обработчик выполняется, потому что у меня есть оператор печати в начале обработчика.
- На этом этапе я ожидал, что основной поток 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()
}