我正在开发一个在gentoo Linux上运行的非常大且复杂的PHP项目,这显然存在PHP信号量的一些问题。由于项目的规模和复杂性,我无法发布代码。我也无法提供再现问题的工作示例。它可能是由于程序的复杂性以非威慑方式引起的。
问题在于:PHP代码正在尝试使用信号量写入和读取共享内存。在产生问题的情况下,执行以下操作:
在时间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
在时间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中的代码行相同)执行以下代码,从共享内存中读取5个字节的数据,$iVarKey
的值为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中的错误?有没有人看起来像类似的东西?有解决方法吗?我可以做些什么来进一步投资这个问题吗?
我真的很感谢这个问题的帮助!
备注:
其他信息:
- 我已经检查了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
的唯一电话似乎永远不会被调用。
答案 0 :(得分:2)
您的代码假定始终获取信号量,这可能不是真的。试试这个
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
}