php - 为什么PHP的sem_acquire会阻塞程序执行?

标签 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);
    

    此操作在时间 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);
    

    此操作在时间 006.78 结束

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

    sem_acquire($this->rSemaphore);
    $mVar = shm_get_var($this->rShm,$iVarKey);
    sem_release($this->rSemaphore);
    

    此操作现在需要大约 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 
  • 阻塞信号量调用sem_get()

    $this->rSemaphore = sem_get(1000000,1,0666,1);
    
  • 唯一涉及 ftok 的调用似乎永远不会被调用。

最佳答案

您的代码假定总是获取信号量,这可能不是真的。试试这个

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

一个潜在的解决方法是使用 flock()而不是信号量函数。缺点是 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
}

关于php - 为什么PHP的sem_acquire会阻塞程序执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23534019/

相关文章:

javascript - 每次插入数据库时​​自动递增 `trackingcode` 列

php - 获取我网站的所有 cookie

php - CakePHP:添加 DISTINCT 以查找导致关联被省略

php - 在调用它之前检查是否存在被覆盖的父方法

java - 信号量和条件的区别(ReentrantLock)

c++ - 通过 Mmap-ed 共享内存传递可变长度的 C 字符串

C - 使用 mmap 通过共享内存读取整数

c - shm_open : Differences between Mac and Linux

c - 如何在 C 中的 fork 进程上使用 POSIX 信号量?

c - 如何确定锁定 posix 信号量的进程的优先级?