Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does PHP's sem_acquire blocks program execution?

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:

  1. 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

  2. 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

  3. 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:

  • If you need additional information, I will try to provide them
  • Please no comments and remarks about PHP4 or the parallel use of two PHP versions.
  • If people think this question does not belong here, please provide guidance.

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.

like image 951
Alex Avatar asked May 08 '14 06:05

Alex


1 Answers

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
}
like image 106
FuzzyTree Avatar answered Sep 20 '22 02:09

FuzzyTree