【问题标题】:SIGTERM signal handler not printing to a consoleSIGTERM 信号处理程序未打印到控制台
【发布时间】:2019-10-18 01:07:53
【问题描述】:

我正在尝试捕获 SIGTERM 信号并在处理程序中从 Linux 守护进程打印一条消息:

void SigStop_Handler(int sig)
{
   D(printf("****************** HANDLED STOP SIGNAL ******************\n"));
   printf("\n");
}

int main(int argc, char *argv[])
{
   signal(SIGTERM, SigStop_Handler);

   while(true)
   {
      //do something
   }

   return 0;    
}

程序作为守护进程运行,从命令行启动:

systemctl start abc

deameon 将通过以下方式停止:

systemctl stop abc

当守护程序停止时,我希望该消息将打印在控制台上。但是,该消息不会打印出来,命令行也不会返回到命令提示符。它确实会在一段时间后返回(超时)。守护程序将停止,但不会打印消息。

我做错了什么?

【问题讨论】:

    标签: c linux signals daemon


    【解决方案1】:

    需要考虑的两件事:接收到信号时终止守护进程,以及获取消息。

    在 systemctl 的上下文中,您希望信号处理程序退出程序。否则, 它只会“打印”消息,然后继续处理。试试

    void SigStop_Handler(int sig)
    {
       D(fprintf(stderr, "****************** HANDLED STOP SIGNAL ******************\n"));
       printf("\n");
       exit(sig+128) ;
    }
    

    此外,鉴于进程作为守护进程运行,stdout 不会连接到终端。相反,它将被重定向到日志文件中。另外,建议使用 stderr 来发送消息,而不是 stdout(参见上面的代码)。另外,请查看您的服务的 StandardOutputStandardErrro 配置条目。

    您当前观察到的延迟发生是因为“systemctl”在发送 TERM 信号后等待几秒钟 - 让守护程序更改终​​止。如果守护进程不是自愿终止,则会发送一个 KILL 信号,这将强制守护进程立即无条件终止。

    【讨论】:

    • 是的,fprintf 有效。但是,即使不使用退出,服务也会停止。就像在 SigStop_Handler 之后,服务的关闭会继续。我假设,在我进入 SigStop_Handler 之前,系统不会关闭服务。
    • 信号处理程序的目标通常是允许从清理、记录等。如果你不想处理这部分,调用信号几乎没有什么好处。
    • 我的想法是通知该服务的停止请求。当收到请求(又名信号)时,我知道我需要停止接受新数据并让后台线程清理队列,停止,然后才调用 exit。当我在信号处理程序中时,该过程被中断。我最初的想法是该处理程序只需设置标志以停止侦听新数据并清理队列。但这行不通,因为如果我不退出处理程序,系统将继续执行默认处理程序。
    • 重点是:因为从 SIGTERM 处理程序调用 threadWorker.join 可能不安全,如何保证 SigStop_Handler 将等待 threadWorker 完成?
    • @查询。 threadWork.join 是 c++ 吗?如果您对它进行多线程编码,并且您希望 threadWorder 完成当前请求(或其他一些关键活动),那么您几乎没有选择:关键部分、信号保持,或者您可以设置全局标志(“terminateASAP”)而不是退出,并让工作线程执行定期检查。这超出了这个问题的范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 2014-02-20
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    相关资源
    最近更新 更多