I am working on a very large and complex PHP project running on gentoo Linux which obviously has some issues with PHP semaphores. Because of the size and complexity of the project I cannot post the code. I also cannot provide a working example that reproduces the problem. It might be caused by the program's complexity in a non-determic manner.
Here is the issue: The PHP code is trying to write and read to/from shared memory using semaphores. In the case that creates the problem, the following actions are done:
At time 006.68 the following code is executed by PHP 4.4.9 to write 5 bytes of data into the shared memory, with $iVarKey
having the value 2010147023
sem_acquire($this->rSemaphore);
shm_put_var($this->rShm, $iVarKey, $mVar);
sem_release($this->rSemaphore);
This action is ended at time 006.69
At time 006.77 the following code is executed by PHP 5.2.10 to read 5 bytes of data from the shared memory, with $iVarKey
having the value 622679600:
sem_acquire($this->rSemaphore);
$mVar = shm_get_var($this->rShm,$iVarKey);
sem_release($this->rSemaphore);
This action is ended at time 006.78
At time 016.01 the following code is executed by PHP 5.2.10 (same lines of code as in #2) to read 5 bytes of data from the shared memory, with $iVarKey
having the value 2010147023 (same as in #1):
sem_acquire($this->rSemaphore);
$mVar = shm_get_var($this->rShm,$iVarKey);
sem_release($this->rSemaphore);
This action now takes about 2 minutes, although the resource/semaphore with the same $iVarKey
has been released about 10 seconds earlier. There are no accesses to the shared memory in the meantime, as I have identified EVERY call to sem_acquire
!
How can it be possible that sem_acquire
blocks the program execution, although it should not. Maybe it is a bug in the version 4.4.9/5.2.10? Has anyone ever seem something similar? Is there a workaround? Is there something I can do to invest this issue further?
I will really appreciate help with this issue!
Remarks:
Additional information:
- I have checked every call of sem_release
, and none of them seem to return a FALSE
. My problem therefore does not arise from a failing release.
- When the system is blocking, ipcs -s
returns the following output, identical to when the system is not blocking
------ Semaphore Arrays --------
key semid owner perms nsems
0x000f4240 0 root 666 3
0x00000001 32769 root 666 3
0x00000000 65538 apache 600 1
The call to sem_get()
for the blocking semaphore is
$this->rSemaphore = sem_get(1000000,1,0666,1);
The only call involving ftok
seem to never gets called.
Your code assumes that the semaphore is always acquired, which may not be true. Try this
if(sem_acquire($this->rSemaphore)) {
$mVar = shm_get_var($this->rShm,$iVarKey);
if(!sem_release($this->rSemaphore)) {
//log error
}
}
else {
//log error
}
One potential workaround is to use flock() instead of the semaphore functions. The downside is that flock()
is slower but depending on your use case it might be fast enough
$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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With