Python 脚本在 SIGINT "terminate called without an active exception when" 后挂起
Python script hangs after SIGINT "terminate called without an active exception when"
我有一个 python 应用程序可以从传感器收集数据。传感器的驱动程序是封闭源代码,我已经围绕它编写了一个包装器以简化其使用。 Linux 上的整个应用程序 运行。该程序具有以下流程。
- Python 调用驱动程序设置。这将启动一个 std::thread,我控制它轮询传感器并将结果数据放入 std::queue。它还调用封闭源驱动程序启动代码,该代码似乎启动了几个线程。
- Python 主线程通过调用 c++ 驱动程序 (driver.getData) 开始循环从传感器的数据队列中挑选东西。一旦有了数据,它就会进行一些缓冲,并在聚合固定数量的样本后将它们写入文件。
- 最终我希望程序停止,所以我按下 ctrl+c 来发送进程 SIGINT。我有一个通过 python signal.signal 函数注册的处理程序,它捕获信号更改布尔值和 returns。我知道处理程序执行是因为我在处理程序的开头有一个打印语句。
- 此时我希望主 python 线程停止循环其 while 循环(因为它检查的条件现在已被处理程序设置为 False)和 运行 我的清理代码。
第 4 步仅在 c++ 线程未 运行ning(从未启动或已停止)时发生。如果线程是 运行ning 并且我正在从传感器数据队列中取出东西,我会得到一个 "terminate called without an active exception" 并且我的应用程序挂起。其他提到此消息的问题指出,作为消息的原因,在退出之前未加入线程,但我的代码从未进入我的关闭代码中的连接语句。
如果非要我猜的话,似乎驱动程序线程之一或我的 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()
}
经过更多的挖掘之后,看起来基本驱动程序正在为 SIGINT 信号注册一个处理程序并在我有机会清理我的线程之前调用 exit。
我有一个 python 应用程序可以从传感器收集数据。传感器的驱动程序是封闭源代码,我已经围绕它编写了一个包装器以简化其使用。 Linux 上的整个应用程序 运行。该程序具有以下流程。
- Python 调用驱动程序设置。这将启动一个 std::thread,我控制它轮询传感器并将结果数据放入 std::queue。它还调用封闭源驱动程序启动代码,该代码似乎启动了几个线程。
- Python 主线程通过调用 c++ 驱动程序 (driver.getData) 开始循环从传感器的数据队列中挑选东西。一旦有了数据,它就会进行一些缓冲,并在聚合固定数量的样本后将它们写入文件。
- 最终我希望程序停止,所以我按下 ctrl+c 来发送进程 SIGINT。我有一个通过 python signal.signal 函数注册的处理程序,它捕获信号更改布尔值和 returns。我知道处理程序执行是因为我在处理程序的开头有一个打印语句。
- 此时我希望主 python 线程停止循环其 while 循环(因为它检查的条件现在已被处理程序设置为 False)和 运行 我的清理代码。
第 4 步仅在 c++ 线程未 运行ning(从未启动或已停止)时发生。如果线程是 运行ning 并且我正在从传感器数据队列中取出东西,我会得到一个 "terminate called without an active exception" 并且我的应用程序挂起。其他提到此消息的问题指出,作为消息的原因,在退出之前未加入线程,但我的代码从未进入我的关闭代码中的连接语句。
如果非要我猜的话,似乎驱动程序线程之一或我的 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()
}
经过更多的挖掘之后,看起来基本驱动程序正在为 SIGINT 信号注册一个处理程序并在我有机会清理我的线程之前调用 exit。