我正在一个非常大而复杂的PHP项目上工作,该项目运行在gentoo Linux上,显然有一些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相同的代码行)从共享内存中读取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版本的bug ?有人看到过类似的东西吗?有解决办法吗?我能做些什么来进一步探讨这个问题吗?
评论:
- 如果你需要更多的信息,我会尽量提供给他们
- 请不要评论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
}