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

C++ CTRL+C Handler having undefined behavior?

我在 Windows 10 上有一个大型 C++ 程序 运行ning,它有一个主系统响应套接字请求和 2 个线程 运行ning 通过单独的套接字实例监视系统客户 class。

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

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

然后 sExit() 函数随机 'exits?',没有完成所有代码。但是程序似乎根据 windows 和退出代码干净地关闭了。 VS2019 未检测到任何问题,程序以 0xc000013a (Windows CTRL+C).

退出

当我尝试调试进入 sExit() 函数时,它会 运行 几行,但在某些时候它 'crashes' 或者只是退出整个程序而没有任何异常或完成功能。它不会每次都发生在同一条线上,而是发生在不同的点。有时 'crashes' 在调用 thread.join() 之前或之后,并且根据日志记录,程序经常在 2 个子线程完成之前崩溃。

下面的配置过去使用 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());
}

当用户在控制台上单击关闭时 window - HandlerRoutine callback ( sExit in your case) receive CTRL_CLOSE_EVENT. with this event - system force terminate your process after SPI_GETHUNGAPPTIMEOUT(默认 5000 毫秒)。无论你在你的过程中做什么(Circumstances - any) - 超时后 - 如果你自己不退出 - 你的过程将被外部终止 STATUS_CONTROL_C_EXIT 代码。这完全有效 "exit in a random place" (实际上你的代码可以在调用终止时的任何地方)

但万一 CTRL_C, CTRL_BREAK - 没有超时 - 寻找最后的 Timeouts 部分