C++CTRL+C处理程序有未定义的行为

C++ CTRL+C Handler having undefined behavior?

本文关键字:未定义 处理 程序 C++CTRL+C      更新时间:2023-10-16

我有一个在Windows 10上运行的大型C++程序,它有一个回答套接字请求的主系统和两个通过套接字客户端类的单独实例运行监控系统的线程。

在软件关闭时(CTRL+C或退出X按钮(,我需要能够优雅地停止2个线程,这些线程通过套接字关闭一些物理设备。

当注册了CTRL+C事件时,会调用sExit()函数。此函数将原子变量kill_child_threads=true设置为在远程线程中循环时终止。不幸的是,当我加入远程线程时,它们似乎没有加入,或者至少加入不会阻止sExit()函数。

则CCD_ 4函数随机"退出?",而不完成所有代码。但该程序似乎根据窗口和退出代码干净地关闭了。VS2019未检测到任何问题,程序以0xc000013a(Windows CTRL+C(退出。

当我尝试将步骤调试到sExit()函数中时,它会运行几行,但在某个时刻它会"崩溃"或只是退出整个程序,而不会出现任何异常或完成函数。它并不是每次都发生在同一条线上,而是发生在不同的点上。它有时会在线程调用之前或之后"崩溃"。join((的调用,根据日志记录,程序通常在两个子线程完成之前崩溃。

下面的配置历史上使用1个线程,但最近添加了第二个线程后,我得到了我认为未定义的行为。

任何调试的帮助或方法都将非常有用
请注意,LOG系统是线程安全的。

Def在main.cpp的顶部;在main(void):内创建线程

//top of main.cpp
std::thread *rotor_thread;
std::thread *heat_thread;
//main()
rotor_thread= new std::thread(TubeControl::rotorThing);
heat_thread= new std::thread(HeatExControl::heatThing);
BOOL WINAPI sExit(DWORD CtrlType)
{
if ((CtrlType == CTRL_CLOSE_EVENT) | (CtrlType == CTRL_C_EVENT)) {
LOG(DEBUG) << "Entering Close Event or Ctrl-C Event";
//Kill Tube rotor thread & spin to ECO mode.
kill_child_threads.store(true, std::memory_order_seq_cst);
try 
{
heat_thread->join();
rotor_thread->join();
}
catch (std::exception & e)
{
LOG(ERROR) << "Issue Killing:" << e.what();
}
//More stuff here on main thread...
//That never executes, or sometimes partially executes.
}

线程1:

void rotorThing(void)
{
while (!kill_child_threads.load(std::memory_order_seq_cst))
{
//Do Thread safe stuff.
//Sleep
std::this_thread::sleep_for(std::chrono::seconds(1));
}
//Program shutting down
try
{
LOG(INFO) << "[Rotor] xxxxxxxxxxxxxxx.";
//Do Thread safe stuff.
}
catch (std::exception & e)
{
LOG(ERROR) << "Issue shutting down tube" << e.what();
}
}

线程2:

void heatThing(void)
{
enum HEAT_STATE { COLD, HOT };
HEAT_STATE heat_state = HEAT_STATE::COLD;
LOG(DEBUG) << "[Heat] Starting Heat Exchanger Monitoring Thread.";
std::string resp = "";
while (!kill_child_threads.load(std::memory_order_seq_cst))
{
//Check tube speed, and Hx temps and flows
hwHxSock->sendCmd("hx,get_inlet_temp");
float itemp = stof(hwHxSock->getRespString());
LOG(DEBUG) << "[Heat Xfer Mon] xxxxxxxxx";
std::this_thread::sleep_for(std::chrono::seconds(5));
}
hwHxSock->sendCmd("hx,get_inlet_temp");
float itemp = stof(hwHxSock->getRespString());
}

当用户在控制台窗口上单击关闭时,HandlerRouine回调(在您的情况下为sExit(将接收CTRL_CLOSE_EVENT。使用此事件-系统强制在SPI_GETHUNGAPPTIMEOUT之后终止进程(默认情况下为5000ms(。无论您在流程中做什么(环境-任何(-在一段时间后-如果您自己不退出-您的流程都将使用STATUS_CONTROL_C_EXIT代码进行外部终止。这恰好产生了"在一个随机的地方退出"的效果(实际上,当调用terminate时,你的代码可以在任何地方(

但在CTRL_C, CTRL_BREAK-没有超时的情况下,在最终中查找超时部分