我有一个在Windows 10上运行的大型C ++程序,该程序具有一个主系统来回答套接字请求,并且有2个线程通过套接字客户端类的单独实例运行监视系统。
在软件关闭时(CTRL + C或退出X按钮),我需要能够正常停止2个线程,这些线程通过套接字关闭了一些物理设备。
注册CTRL + C事件时,将调用sExit()
函数。
此函数设置原子变量kill_child_threads=true
来杀死远程线程中的while循环。不幸的是,当我加入远程线程时,它们似乎没有加入,或者至少加入没有阻止sExit()
函数。
然后,sExit()
函数会随机“退出?”,而无需完成所有代码。但是该程序似乎根据Windows和退出代码完全关闭了。 VS2019未检测到任何问题,程序以0xc000013a(Windows CTRL + C)退出。
当我尝试调试进入sExit()
函数的步骤时,它将运行几行,但是在某些时候它“崩溃”或仅退出整个程序,而没有任何异常或功能完成。它并非每次都在同一行上发生,而是在不同点上发生。有时它在调用thread.join()之前或之后“崩溃”,并且基于日志记录,该程序通常在2个子线程完成之前崩溃。
以下配置在历史上只能使用1个线程,但是最近添加了第二个线程后,我得到了我认为未定义行为的信息。
任何帮助或调试方法都将非常有帮助。
请注意,LOG系统是线程安全的。
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());
}