2012-10-03 24 views
2

当应用程序(C++守护进程,在我的情况下)接收到SIGTERM或SIGINT时,记录关闭消息的正确方法是什么?记录来自SIGTERM的消息

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

+0

什么是环境:一个shell脚本,C程序,Perl脚本,由HTTP服务器执行的PHP脚本等? – aqn

+0

@aqn - C++守护进程。我会更新我的问题。谢谢。 –

+1

使用管道或(UDP)套接字将消息发送到主程序循环或单独的记录过程。 – wildplasser

回答

0

记录无法从处理器来完成,但之后:

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源借来的。

1

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

#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"); 
     } 
    } 
} 

该示例可以很容易地扩展到集成到事件循环中。