4

我正在尝试在 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% 安全的,因为获取信号量并设置全局不是原子的,但可能比在等待时阻塞信号更好。

4

3 回答 3

7

Are you sure sem_wait() causes signals to be blocked? I don't think this is the case. The man page for sem_wait() says that the EINTR error code is returned from sem_wait() if it is interrupted by a signal.

You should be able to handle this error code and then your signals will be received. Have you run into a case where signals have not been received?

I would make sure you handle the error codes that sem_wait() can return. Although it may be rare, if you want to be 100% sure you want to cover 100% of your bases.

于 2009-06-01T23:39:37.737 回答
0

Are you sure you are approaching the problem correctly? If you want to wait for a child terminating, you may want to use the waitpid() system call. As you observed, it is not reliable to expect the child to do the sem_post() if it may receive signals.

于 2009-06-02T00:04:22.443 回答
0

I know this is old, but for the benefit of those still reading this courtesy of Google...

The simplest (and only?) robust solution to this problem is to use a System V semaphore, which allows the client to acquire the semaphore resource in a way which is automatically returned by the kernel NO MATTER HOW THE PROCESS EXITS.

于 2012-10-11T22:40:02.223 回答