不使用pkill优雅退出程序的最佳方法

时间:2012-01-18 07:35:47

标签: c++ linux

我目前正在使用脚本调用pkill来终止我的C ++程序。 但是我注意到使用pkill时没有从我的跟踪中调用析构函数。

还有另一种好方法可以优雅地退出程序吗? pkill似乎有些不整洁,并且缓冲区中的某些日志不会被记录。我希望能够刷新我的fstream并以编程方式关闭所有资源(而不是依靠O / S来清理我的混乱)。

应用程序全天候运行没有任何问题,我唯一想停止它的是维护期间。该应用程序没有任何用户界面供我输入exit。

4 个答案:

答案 0 :(得分:4)

除非您修改目标应用程序,否则我看不到任何方法。

请考虑以下事项:

int main()
{
   MyClass a;
   while ( true )
   {
   }
}

你必须告诉程序退出循环。但除非你的应用程序有一些信号处理机制,否则这似乎是不可能的。

你需要这样的东西:

int main()
{
   MyClass a;
   while ( !killSignalReceived() )
   {
   }
}

答案 1 :(得分:4)

您可以通过以下几行为SIGTERM定义信号处理程序来实现:

包含块中的某处:

#include <signal.h>
#include <stdio.h>

是的,我们正在做C风格!

代码初始化部分的某处:

signal (SIGTERM, handler);

然后定义信号处理程序代码(刷新所有内容等):

void handler(int num) 
{
  // we might use this handler for many signals
  switch (num)
  {
    case SIGTERM:
      // clean up code.
      break;
  }
}

现在,当您运行pkill <app>,其中<app>是可执行文件的名称时,handler()的代码将会运行。

如果没有开关,默认的SIGTERM信号将被发送到应用程序。如果您选择使用不同的信号,您必须确保发送与handler()中“捕获”相同的信号。

相关信息可以在man 7 signal找到,当然也可以找到man kill

答案 2 :(得分:4)

除了Zrvan's answer之外,请注意,只能从信号处理程序中安全地调用一组受限制的函数。 signal(7)手册页和Posix标准要求只能在信号处理程序中直接或间接调用异步信号安全函数。请注意,printfmalloc在信号处理程序中并不安全。信号处理程序的代码编写起来很棘手(并且您无法轻松调试它,因为信号发送是不可重现的)。

正如Glibc文档所示,您的信号处理程序可以设置一个volatile sig_atomic_t变量,您的主循环[s]将测试和处理。

如果应用程序是基于事件的,您还可以决定某个套接字或命名管道专用于控制它。该事件循环(可能使用select(2)poll(2),甚至pselectppoll)可以处理管道或套接字上的控制消息。

您可能会对像libevent这样的事件循环库感兴趣。您还可以使用HTTP onionWt等HTTP服务器库。您也可能对SNMP或D-bus感兴趣。

克服信号处理程序限制的一个技巧是让它们在管道上写入同一个进程,例如, Qt's doc建议。然后事件循环将处理该管道上的读数。

如果您的应用程序是多线程的,那么信号处理就更棘手了。一些信号被传递到一个单独的线程。

答案 3 :(得分:3)

最好的方法是处理程序中的信号,然后使用kill发送该信号。在信号处理程序中,标记一个将导致主循环结束的标志。