我正在处理一个运行在 gentoo Linux 上的非常大且复杂的 PHP 项目,它显然存在一些 PHP 信号量问题。由于项目的规模和复杂性,我无法发布代码。我也无法提供重现该问题的工作示例。这可能是由程序的复杂性以非确定的方式引起的。
这里是问题所在:PHP 代码正在尝试使用信号量向/从共享内存写入和读取。在产生问题的情况下,将执行以下操作:
在时间 006.68,PHP 4.4.9 执行以下代码,将 5 个字节的数据写入共享内存,
$iVarKey
的值为 2010147023sem_acquire($this->rSemaphore); shm_put_var($this->rShm, $iVarKey, $mVar); sem_release($this->rSemaphore);
此操作在时间 006.69 结束
在时间 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 结束
在时间 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/