linux - 记录来自 SIGTERM 的消息

标签 linux logging sigterm

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

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

最佳答案

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

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

关于linux - 记录来自 SIGTERM 的消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12708984/

相关文章:

linux - 在装有 linux 的系统上检测网卡和端口

asp.net - ILoggingBuilder 没有参数为 0 的 AddEventSourceLogger。如何初始化此日志记录

ruby - Thin 不响应 SIGINT 或 SIGTERM

mongodb - npm 在 ctrl+c 上运行 poststop 脚本

linux - 在 Debian 11 (Bullseye) 上,docker 容器内的/proc/self/cgroup 不显示 docker 信息

linux - 如何在多行 linux 上进行精确匹配

C++/Qt - 可选参数默认为 NULL

google-app-engine - GAE/J 请求日志格式分解

C++ 传递 Boost::log 严重级别作为函数的参数

ruby - 如何测试 RSpec 中的信号处理,特别是 SIGTERM 的处理?