![](/img/trans.png)
[英]Is there a full memory barrier around sem_post(sem_t * sem) and sem_wait(sem_t * sem)?
[英]Signal safe use of sem_wait()/sem_post()
我试图在Linux上创建一个包装器,它控制一次允许多少次并发执行。 为此,我使用系统范围的计数信号量。 我创建信号量,执行sem_wait()
,启动子进程,然后在子进程终止时执行sem_post()
。 那样就好。
问题是如何安全地处理发送给这个包装器的信号。 如果它没有捕获信号,则命令可能会在不执行sem_post()
情况下终止,从而导致信号量计数永久减少1。 所以,我创建了一个执行sem_post()
的信号处理程序。 但是,仍有一个问题。
如果在执行sem_wait()
之前附加了处理程序,则信号可能在sem_wait()
完成之前到达,从而导致sem_post()
在没有sem_wait()
情况下发生。 如果我在设置信号处理程序之前执行sem_wait()
,则可以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%安全,因为获取信号量并设置全局不是原子的,但可能比等待时阻塞信号更好。
你确定sem_wait()
导致信号被阻止吗? 我不认为是这种情况。 sem_wait()
的手册页说如果它被信号中断,则从sem_wait()
返回EINTR
错误代码。
您应该能够处理此错误代码,然后您的信号将被接收。 您是否遇到未收到信号的情况?
我会确保你处理sem_wait()
可以返回的错误代码。 虽然可能很少见,但如果你想100%确定你想要100%的基数。
我知道这已经过时了,但为了那些仍在阅读Google礼貌的人的利益......
这个问题的最简单(也是唯一的)稳健解决方案是使用System V信号量,它允许客户端以一种内核自动返回的方式获取信号量资源。无论过程如何排除。
你确定你正确地接近了这个问题吗? 如果要等待子进程终止,可能需要使用waitpid()
系统调用。 正如您所观察到的,如果孩子可能接收到信号,那么期望孩子做sem_post()
是不可靠的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.