c - 对循环中的信号进行非阻塞检查

标签 c linux pthreads signals

我在一个应用程序中有一个线程,它有一个像这样的循环:

...
while (1)
{
    checkDatabase();
    checkChildren();

    sleep(3);
}
...

checkDatabase() 是不言自明的; checkChildren() 只需调用 waitpid(-1, &status, WNOHANG) 来处理已退出或收到信号的子进程。

该应用程序运行良好,但它具有默认信号处理。问题是这个父进程有很多线程(现在不用担心子进程)而且我对同步信号没有任何经验,更不用说在 POSIX 线程应用程序中了。我以前使用过 signal(),但显然它是不可移植的,而且无论如何它都不能满足我的需要。我完全没有使用 sigaction 方法的经验,而且我找不到关于如何填充结构等的好文档。

我需要做的是在上面的循环中同步捕获终止信号,如 SIGINTSIGTERMSIGQUIT(我需要完全忽略 SIGPIPE 以便我可以从 IO 方法中捕获 EPIPE 错误),所以它看起来像这样:

...
while (1)
{
    checkDatabase();
    checkChildren();
    checkForSignals();

    sleep(3);
}
...

所有其他线程不应该与信号有任何关系;只有执行这个循环的线程应该知道它。而且,很明显,它需要是一个非阻塞检查,这样循环才不会在第一次迭代时阻塞。如果发现信号,调用的方法将整理其他线程并销毁互斥量,等等。

有人可以给我提个醒吗?非常感谢。

最佳答案

(根据问题的评论,为了完整性,此解决方案试图避免信号处理程序。)

可以阻止通过 sigprocmask() 引发的信号(或者更确切地说,pthread_sigmask() 因为您使用的是线程)。从那里开始,发出但被阻止的信号可通过 sigpending() 获得。 .

因此,您可以做类似的事情(为简洁起见省略了错误检查):

sigset_t blocked;
sigemptyset(&blocked);
sigaddset(&blocked, SIGINT);
sigaddset(&blocked, SIGTERM);
sigaddset(&blocked, SIGQUIT);
pthread_sigmask(SIG_BLOCK, &blocked, NULL); // Block SIGINT, SIGTERM and SIGQUIT.
signal(SIGPIPE, SIG_IGN);                   // Ignore SIGPIPE.

然后,稍后:

void checkForSignals(void)
{
    sigset_t pending;
    sigpending(&pending);
    if (sigismember(&pending, SIGINT)) {
        // Handle SIGINT...
    }
    if (sigismember(&pending, SIGTERM)) {
        // Handle SIGTERM...
    }
    if (sigismember(&pending, SIGQUIT)) {
        // Handle SIGQUIT...
    }
}

由于 sigpending() 不阻塞,这似乎符合您的要求。

关于c - 对循环中的信号进行非阻塞检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8790398/

相关文章:

c - 将打印哪个值?

c - 变量作为 pthread 中的参数

C运行外部程序出现错误

c++ - 大量对象导致 Segmentation Fault

c++ - 在 Visual Studio 中为远程环境使用自定义构建命令

c - 寄存器存储类的范围是什么?

c - 有没有办法在不终止其他线程的情况下生成新进程?

c - pthread rwlock : rdlock inside wrlock

c - 在特定值的转换工具中获取输出为 "-nan"

c - 将多个参数传递给 GTK 中的回调函数