我正在尝试在 Linux 上创建一个包装器,它控制一次允许多少个并发执行。为此,我使用了系统范围的计数信号量。我创建信号量,执行 a sem_wait()
,启动子进程,然后在子进程sem_post()
终止时执行 a 。没事儿。
问题是如何安全地处理发送到这个包装器的信号。如果它没有捕捉到信号,则命令可能会在不执行 a 的情况下终止sem_post()
,从而导致信号量计数永久减少 1。所以,我创建了一个信号处理程序来执行sem_post()
. 但是,还是有问题。
如果在sem_wait()
执行之前附加了处理程序,则信号可能会在sem_wait()
完成之前到达,从而导致 asem_post()
发生而没有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% 安全的,因为获取信号量并设置全局不是原子的,但可能比在等待时阻塞信号更好。