为什么PHP的sem_acquire会阻止程序执行?

Ale*_*lex 11 php semaphore shared-memory

我正在研究一个在gentoo Linux上运行的非常大而复杂的PHP项目,这显然存在PHP信号量的一些问题.由于项目的规模和复杂性,我无法发布代码.我也无法提供再现问题的工作示例.它可能是由程序的复杂性以非威慑方式引起的.

问题出在这里:PHP代码正在尝试使用信号量写入和读取共享内存.在产生问题的情况下,执行以下操作:

  1. 在时间006.68,PHP 4.4.9执行以下代码,将5个字节的数据写入共享内存,$iVarKey其值为2010147023

    sem_acquire($this->rSemaphore);
    shm_put_var($this->rShm, $iVarKey, $mVar);
    sem_release($this->rSemaphore);
    
    Run Code Online (Sandbox Code Playgroud)

    此操作在006.69时结束

  2. 在时间006.77,PHP 5.2.10执行以下代码,从共享内存中读取5个字节的数据,$iVarKey其值为622679600:

    sem_acquire($this->rSemaphore);
    $mVar = shm_get_var($this->rShm,$iVarKey);
    sem_release($this->rSemaphore);
    
    Run Code Online (Sandbox Code Playgroud)

    此操作在006.78时结束

  3. 在时间016.01以下代码是由PHP 5.2.10(的代码相同的行中#2)执行,以从共享存储器读出5个字节的数据,以$iVarKey具有值2010147023(同#1):

    sem_acquire($this->rSemaphore);
    $mVar = shm_get_var($this->rShm,$iVarKey);
    sem_release($this->rSemaphore);
    
    Run Code Online (Sandbox Code Playgroud)

    此操作现在大约需要2分钟,尽管具有相同的资源/信号量$iVarKey已提前约10秒发布.在此期间没有访问共享内存,因为我已经确定了每次调用sem_acquire!

如何sem_acquire阻止程序执行,尽管它不应该.也许这是版本4.4.9/5.2.10中的错误?有没有人看起来像类似的东西?有解决方法吗?我可以做些什么来进一步投资这个问题吗?

我真的很感激这个问题的帮助!

备注:

  • 如果您需要其他信息,我会尝试提供
  • 请不要评论和评论PHP4或并行使用两个PHP版本.
  • 如果人们认为这个问题不属于此,请提供指导.

附加信息: - 我已经检查过每次通话sem_release,但似乎没有人回复FALSE.因此,我的问题并非来自失败的释放.- 当系统阻塞时,ipcs -s返回以下输出,与系统未阻塞时相同

    ------ Semaphore Arrays --------
    key        semid      owner      perms      nsems     
    0x000f4240 0          root      666        3         
    0x00000001 32769      root      666        3         
    0x00000000 65538      apache    600        1 
Run Code Online (Sandbox Code Playgroud)

Fuz*_*ree 3

您的代码假设信号量始终被获取,这可能不正确。尝试这个

if(sem_acquire($this->rSemaphore)) {
    $mVar = shm_get_var($this->rShm,$iVarKey);
    if(!sem_release($this->rSemaphore)) {
      //log error
    }
}
else {
    //log error
}
Run Code Online (Sandbox Code Playgroud)

一种可能的解决方法是使用集群()而不是信号量函数。缺点是速度flock()较慢,但​​根据您的用例,它可能足够快

$file = "/tmp/my_semaphore";
$fp = fopen($file,"r+");

if(flock($fp, LOCK_EX)) { // wait/acquire lock
    shm_put_var($this->rShm, $iVarKey, $mVar);
    if(!flock($fp, LOCK_UN)) { //release file lock
      //log error
    }
}
else {
    //something went wrong, unable to attain lock
}
Run Code Online (Sandbox Code Playgroud)