【问题标题】:How can you cleanly terminate a process in C++11?如何在 C++11 中干净地终止进程?
【发布时间】:2015-11-10 08:44:19
【问题描述】:

我想知道是否有一种好方法可以在一段时间后终止我用 C++11 编写的进程?

在我的进程中,我有一个带有纯虚函数run() 的主类,它运行可能在通信进程中被阻塞的主程序。我希望我的 run() 函数在一段时间后被强制完成(即使被阻塞),并且我的主类的析构函数(以及所有成员的析构函数)被调用。

现在我有一个计时器,它通过回调调用std::terminate

namespace Timer
{
    void start(Duration time, function<void()> task)
    {
        thread([time, task]() {
            this_thread::sleep_for(time);
            task();
        }).detach();
    }
}

【问题讨论】:

  • 如果run()函数不返回,就不能干净地结束程序。也许你可以在一个线程中运行run(),并在其上调用thread::detach():主析构函数将被调用,但我不会称之为clean
  • 我也遇到了这个问题,一个程序可能会卡在通信中。我已经为其添加了心跳机制,所以我知道每 X 秒(在我的情况下是每 45 秒)将接收和发送一条消息,然后超时一分钟。所以我从来没有遇到过卡住并等待消息的情况。当然最坏的情况是程序需要 45 秒才能关闭,但它是否干净!
  • 如果一个(非分离的)线程被阻塞,它不能在不先解除阻塞的情况下优雅地终止。您必须通过例如使用等待/通知或使用wait_for或类似方法定期检查状态来在语法上控制它。
  • 我无法解锁额外的库,我不想等待通信超时(这与通信问题无关)。我只是想强制程序在一段时间后完成,以便能够及时正确地停止进程(调用所有析构函数)。如果主程序在定时器之前完成,它也应该正确终止(运行时间可以比定时器短,但永远不会长)。
  • run 包裹在一个线程中。如果它没有及时完成,只需正常退出即可。您将正确关闭run 以上的所有内容。 run下面的东西你不控制,反正也没有希望让它们优雅退出。

标签: c++ multithreading c++11 terminate


【解决方案1】:

真正的解决方案是处理原因而不是症状:

  • 症状:run 函数永不结束
  • 原因:通信请求永远不会结束

大多数通信(输入)函数都是可中断的,或者具有本机超时。如果您的通信例程没有本地超时,您可以(也许)使用alarm Posix 调用将它们包装起来,该调用应该干净地中断它们并允许 run 函数干净地退出。

您只需要注意alarm 在后台使用信号这一事实,因此您不能阻止SIG_ALRM,但您可以使用它来安装一个存储某处的信号处理程序那就是已经被调用了。

恕我直言,与直接使用std::terminate 终止程序相比,它会更简单、更干净、关注点分离更好。

上面只处理run 永远不会结束的情况。如果你想限制它的运行时间,你应该在你的代码中确定可中断的地方来测试允许的运行时间是否用尽,并始终对所有可能阻塞的通信 IO 设置超时。

【讨论】:

  • 你没有回答我的问题。 run() 确实结束了。但这可能需要比预期更多的时间。我想强制run() 在它太长的情况下完成。它可能在通信读取中被阻止。
【解决方案2】:

我猜你是在 Linux 或其他一些 POSIX 系统上。 Event loops 和 polling 在 C++11 中没有标准化,需要操作系统特定的东西。

您的事件循环不应该被长时间阻塞。它应该有一些有限的 - 而不是太大的 - 超时。在 POSIX 上,在事件循环中使用 poll(2) 并设置合理的超时时间(例如一秒)。或者,使用pipe(进程内部)来触发事件循环(因此其他一些线程 - 甚至是信号处理程序 - 将在该管道上使用write(2),并且事件循环将轮询它并read 它,并且可能会停止,因此从run返回)

有关相关提示,另请参阅 thisthat

【讨论】:

    【解决方案3】:

    最好的解决方案是将run() 包裹在一个线程中。

    std::thread([&]()
    {
       run();
       finish.notify_all();
    }).detach();
    
    std::unique_lock<std::mutex> lock(waitFinish);
    finish.wait_for(lock, time);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-07
      • 1970-01-01
      • 2011-11-25
      • 1970-01-01
      • 2010-11-30
      • 2010-11-14
      相关资源
      最近更新 更多