【问题标题】:Logging a message from SIGTERM记录来自 SIGTERM 的消息
【发布时间】:2012-09-24 09:50:26
【问题描述】:

当应用程序(在我的例子中是 C++ 守护程序)收到 SIGTERM 或 SIGINT 时,记录关闭消息的正确方法是什么?

根据CERTsignal(7) manpage,从信号处理程序调用许多函数(可能包括大多数日志库使用的函数)是不安全的。

【问题讨论】:

  • 环境是什么:shell脚本、C程序、Perl脚本、HTTP服务器执行的PHP脚本等?
  • @aqn - C++ 守护进程。我会更新我的问题。谢谢。
  • 使用管道或 (UDP) 套接字将消息发送到主程序循环或单独的日志记录进程。

标签: linux logging sigterm


【解决方案1】:

Vlad Lazarenko 今年早些时候就这个话题写了一篇很棒的blog post。在 Linux 上,它归结为使用signalfd(2) 创建一个信号描述符并使用诸如poll(2)epoll_wait(2) 之类的事件循环。这是弗拉德从描述符中读取的示例

#include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define handle_error(msg)                               \
    do { perror(msg); exit(EXIT_FAILURE); } while (0)

int
main(int argc, char *argv[])
{
    sigset_t mask;
    int sfd;
    struct signalfd_siginfo fdsi;
    ssize_t s;

    sigemptyset(&mask);
    sigaddset(&mask, SIGINT);
    sigaddset(&mask, SIGQUIT);

    /* Block signals so that they aren't handled
       according to their default dispositions */

    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
        handle_error("sigprocmask");

    sfd = signalfd(-1, &mask, 0);
    if (sfd == -1)
        handle_error("signalfd");

    for (;;) {
        s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
        if (s != sizeof(struct signalfd_siginfo))
            handle_error("read");

        if (fdsi.ssi_signo == SIGINT) {
            printf("Got SIGINT\n");
        } else if (fdsi.ssi_signo == SIGQUIT) {
            printf("Got SIGQUIT\n");
            exit(EXIT_SUCCESS);
        } else {
            printf("Read unexpected signal\n");
        }
    }
}

此示例可以轻松扩展以集成到事件循环中。

【讨论】:

    【解决方案2】:

    日志记录可以不是从处理程序完成,而是在它之后完成:

    int received_sigterm = 0;
    
    void
    sigterm_handler(int sig)
    {
      received_sigterm = 1;
    }
    
    void
    loop(void)
    {
      for(;;) {
        sleep(1);
        if (received_sigterm)
          log("finish\n");
      }
    }
    
    int
    main()
    {
      log("start\n");
      signal(SIGTERM, sigterm_handler);
      loop();
    }
    

    这个概念是从 openssh-6.1 来源借来的。

    【讨论】:

      猜你喜欢
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      • 2013-10-17
      相关资源
      最近更新 更多