我在一个应用程序中有一个线程,它有一个像这样的循环:
...
while (1)
{
checkDatabase();
checkChildren();
sleep(3);
}
...
checkDatabase()
是不言自明的; checkChildren()
只需调用 waitpid(-1, &status, WNOHANG)
来处理已退出或收到信号的子进程。
该应用程序运行良好,但它具有默认信号处理。问题是这个父进程有很多线程(现在不用担心子进程)而且我对同步信号没有任何经验,更不用说在 POSIX 线程应用程序中了。我以前使用过 signal()
,但显然它是不可移植的,而且无论如何它都不能满足我的需要。我完全没有使用 sigaction
方法的经验,而且我找不到关于如何填充结构等的好文档。
我需要做的是在上面的循环中同步捕获终止信号,如 SIGINT
、SIGTERM
和 SIGQUIT
(我需要完全忽略 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/