我正在尝试在Linux上创建一个包装器,它控制同时允许多少个并发执行的东西。为此,我使用了一个系统范围的计数信号量。我创建信号量,执行sem_wait(),启动子进程,然后在子进程终止时执行sem_post()。这很好。
问题是如何安全地处理发送到此包装器的信号。如果它没有捕捉到信号,该命令可能会在不执行sem_post()的情况下终止,从而导致信号量计数永久减少1。因此,我创建了一个执行sem_post()的信号处理程序。但是,仍然存在一个问题。
如果在执行sem_wait()之前附加了处理程序,则信号可能会在sem_wait()完成之前到达,从而导致在没有sem_wait()的情况下发生sem_post()。如果我在设置信号处理程序之前执行sem_wait(),则可以进行相反的操作。
显而易见的下一步是在设置处理程序和sem_wait()期间阻止信号。这是我现在所拥有的伪代码:
void handler(int sig)
{
sem_post(sem);
exit(1);
}
...
sigprocmask(...); /* Block signals */
sigaction(...); /* Set signal handler */
sem_wait(sem);
sigprocmask(...); /* Unblock signals */
RunChild();
sem_post(sem);
exit(0);现在的问题是sem_wait()可能会阻塞,在此期间,信号会被阻塞。试图终止进程的用户最终可能会求助于"kill -9“,这是我不想鼓励的行为,因为我无论如何都无法处理这种情况。我可以在一小段时间内使用sem_trywait()并测试sigpending(),但这会影响公平性,因为不再能保证等待信号量时间最长的进程下一步会运行。
这里有没有一个真正安全的解决方案,允许我在获取信号量的过程中处理信号?我正在考虑求助于“我是否有信号量”全局函数并移除信号阻塞,但这并不是100%安全的,因为获取信号量并设置全局函数不是原子的,但可能比在等待时阻塞信号要好。
发布于 2009-06-01 23:39:38
您确定sem_wait()导致信号被阻止吗?我认为情况并非如此。man page for sem_wait()表示,如果被信号中断,则从sem_wait()返回EINTR错误代码。
您应该能够处理此错误代码,然后您的信号将被接收。您是否遇到过信号未被接收到的情况?
我会确保您处理sem_wait()可以返回的错误代码。尽管这可能很少见,但如果你想100%确定你想要100%地覆盖你的基础。
发布于 2009-06-02 00:04:22
你确定你处理这个问题是正确的吗?如果您想等到子进程终止,则可能需要使用waitpid()系统调用。正如您所观察到的,如果孩子可能接收到信号,那么期望它做sem_post()是不可靠的。
发布于 2012-10-12 06:40:02
我知道这很古老,但为了那些仍在阅读谷歌提供的这篇文章的人的利益…
最简单的(也是唯一的?)这个问题的健壮解决方案是使用System V信号量,它允许客户端以内核自动返回的方式获取信号量资源,无论进程如何退出。
https://stackoverflow.com/questions/937289
复制相似问题