c - 信号安全使用 sem_wait()/sem_post()

标签 c posix

我正在尝试在 Linux 上创建一个包装器,它控制一次允许执行多少个并发执行。为此,我使用了系统范围内的计数信号量。我创建信号量,执行 sem_wait(),启动子进程,然后在子进程终止时执行 sem_post()。没关系。

问题是如何安全地处理发送到这个包装器的信号。如果它没有捕捉到信号,该命令可能会在不执行 sem_post() 的情况下终止,从而导致信号量计数永久减一。因此,我创建了一个执行 sem_post() 的信号处理程序。但是,还是有问题。

如果处理程序在 sem_wait() 执行之前附加,信号可能在 sem_wait() 完成之前到达,导致 sem_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% 安全,因为获取信号量和设置全局不是原子的,但可能比等待时阻塞信号更好。

最佳答案

您确定 sem_wait() 会导致信号被阻塞吗?我认为情况并非如此。 man page for sem_wait()EINTR 如果它被信号中断,则从 sem_wait() 返回错误代码。

您应该能够处理此错误代码,然后您的信号将被接收。您是否遇到过收不到信号的情况?

我会确保您处理 sem_wait() 可以返回的错误代码。尽管这种情况可能很少见,但如果您想 100% 确定要覆盖 100% 的碱基。

关于c - 信号安全使用 sem_wait()/sem_post(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/937289/

相关文章:

c - 使用 mmap API 时内存映射长度的意义是什么?

regex - 奇怪的 sed 行为

使用 posix c 函数转换字符编码

c - Linux 3.13 内核模块设置 procfile_read 文件结束条件

c - : if ( test == ( void * ) -1 )中的 "( void * ) "是什么意思

c - 使用带有指针的结构读取二进制文件中的某个位置

c - 为什么我的 if 语句在不应该激活的情况下却激活了?

c - 指针和 getstring 函数

c - Sqlite3 - 试图在回调中填充结构

c++ - OpenCV:如何填充具有每个像素的每种 RGB 颜色值的 rgb 图像?