信号处理程序访问队列数据结构(竞争条件?)

时间:2011-11-16 02:55:59

标签: c++ shell exec race-condition signal-handling

我目前正在用C ++编写一个小shell。

作业和与它们相关的PID存储在作业指针(job *)的队列中。运行新作业时,会将有关它的信息添加到队列中。由于可以同时处理多个作业,并且可以随时在shell控制台输入新作业,因此我有一个信号处理程序可以等待已终止的作业。

当作业终止时,我需要从活动作业队列中删除它的信息并将其移动到已终止作业的双端队列中。但是,当另一个作业停止时,可能会将用户的新作业添加到队列中。

在这种情况下,他们的insert队列操作将被暂停,我的信号处理程序将被调用,这将执行它的pop操作。

我正在努力了解如何解决这种潜在的竞争状况,因为我想在此过程中可能会发生腐败。我不能使用互斥锁,因为如果中断的父进程当时正在使用队列,则会发生死锁。

我看到一些关于C++11能够进行用户声明的原子操作的信息,以及有关tasklet的信息。我不确定这些是否与我的问题相关。

有趣的是,我用作参考的示例shell(MSH - http://code.google.com/p/mini-shell-msh/)似乎没有对这些条件进行任何处理。信号处理程序立即修改作业列表以及主控制台。也许我在这里可以忽略一些东西?

与往常一样,所有反馈都是适当的。

2 个答案:

答案 0 :(得分:4)

你有几种方法可以避免竞争条件。

  • 使用等待空闲(原子)队列作为作业指针;
  • 使用任何其他类型的队列,但使用sigprocmask(在非处理程序代码中)并在sa_mask调用中使用正确的sigaction值保护它;
  • 根本不使用信号处理程序,使用一些非便携式系统调用,允许以同步方式处理信号:在Linux中,可以使用signalfd,不确定其他平台。

答案 1 :(得分:1)

您需要在非处理程序代码中的关键部分周围禁用sigprocmask()的信号。这类似于内核中的设备驱动程序在更新与中断处理程序共享的结构时禁用驱动程序的用户一半中的中断。