捕获 SIGTERM,并 sleep 阻止它工作

标签 c sigterm

我有一些用 C 编写的代码(在 ubuntu 17 上工作):

void sig_stop(int sig_num) {
    /* Some cleanup that needs to be done */
}

void some_routine(const char *array[], const int length) {
    /* Initialization */
    signal(SIGTERM, sig_stop);

    while (true) {
        /* Some function */

        /* I have this sleep to minimize the load on the CPU 
            as I don't need to check the conditions here 
            all the time. */
        sleep(5);
    }
}

每当我包括 5 分钟 sleep (sleep(5)) 时,似乎都没有调用 sig_stop。但是,当我注释掉 sleep(5) 时,sig_stop 清理工作正常。我对如何捕获 SIGTERM 的理解有问题吗?

如果我不能使用 sleep 函数,是否有更好的方法让程序“休眠”,以便它仅每 x 分钟运行一次循环,或者以最小化CPU 负载?

最佳答案

sleep() 和信号

sleep() 不应阻止信号被捕获和信号处理程序被执行。来自manpage for sleep() (强调我的):

sleep() causes the calling thread to sleep either until the number of real-time seconds specified in seconds have elapsed or until a signal arrives which is not ignored.

举个例子...

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

static volatile sig_atomic_t flag = 0;

static void sig_stop(int signum) { flag = 1; }

int main(void) {
    int secs_remaining = 0;
    signal(SIGTERM, sig_stop);

    while (!flag) {
        printf("Sleeping at time %d\n", time(NULL));
        secs_remaining = sleep(5);
    }
    printf(
        "Flag raised. Exiting at time %d. sleep() was interrupted %d seconds "
        "early ...\n",
        time(NULL), secs_remaining);

    return 0;
}

请注意 - 在它被信号中断的情况下 - sleep() 返回 sleep 剩余的秒数。例如,如果它提前 3 秒被中断,它将返回 3。如果没有被中断,它将返回0

编译为 gcc -o test test.c 并运行。然后从另一个终端运行

pkill -15 test

您将看到类似于以下内容的输出...

Sleeping at time 1532273709
Flag raised. Exiting at time 1532273711. sleep() was interrupted 2 seconds early ...

顺便说一句... sleep(x) 睡了 x - 而不是分钟。

signal()sigaction()

由于与 signal() 相关的可移植性问题,通常建议改用 sigaction()sigaction() 的使用如下所示。

int main(void) {
    struct sigaction sa;

    sa.sa_flags = 0;
    sigemptyset(&sa.sa_mask);
    sa.sa_handler = sig_stop;
    if (sigaction(SIGTERM, &sa, NULL) == -1) {
        perror("sigaction");
        return 1;
    }
    // Etc.
}

如您所见,sigaction() 的用法比 signal() 的用法更冗长。也许这就是人们有时仍然使用 signal() 的原因。

关于捕获 SIGTERM,并 sleep 阻止它工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51464443/

相关文章:

linux - 信号处理/子进程的传统做法

django-celery - Celery 任务在本地运行时在正常关闭时重新排队进入代理,但尽管配置相同但在 kubernetes 中丢失

c - 空指针操作

c - 将外部文件的输出存储在变量中

C 指针管理(地址、取消引用、重新分配)

c - 在C中打印二维字符数组

macOS 上的 Swift : Running code on termination of background app

c# - Windows 上是否有 posix SIGTERM 替代方案? -(控制台应用程序的温和杀戮)

python - 服务器重启后守护进程的 PID 文件挂起

arrays - 函数中 int* a 和 int (*a)[N] 的区别?