Skip to content
Advertisement

PHP flock does not lock second run of the script

I trying to implmente a simpler version of the code in this answer: How to detect whether a PHP script is already running?

The problem described here is my EXACT situation. I want to prevent cron from launching the same script if it’s already running.

I started with this simple test code:

<?php 

   $script_name = __FILE__;
   $lock_file_name = basename($script_name, ".php") . ".lock";
   $fp = fopen($lock_file_name, "c");

   if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
       //ftruncate($fp, 0);      // truncate file
       //fwrite($fp, "Write something heren");
       //fflush($fp);            // flush output before releasing the lock
       flock($fp, LOCK_UN);    // release the lock
       echo "GOT LOCKn";
       sleep(20);
   } else {
       echo "Couldn't get the lock!n";
   }

   flock($fp, LOCK_UN);    // release the lock
   fclose($fp);

   
?>

As I understand it, I launch this code in one console and read the Got Lock. If I launch it in another console the I should get the Coudn’t get the lock message. Howver I get the Got Lock message both times.

What am I doing wrong?

Advertisement

Answer

The file is only locked for the duration of the script. Once the PHP finishes its activities the script tereminates and then the OS unlocks the file.

Note that your sleep(20) call is coming after you have unlocked the file, so there is no pause when the file is locked. So it sounds like you’re in effect calling the single script twice in sequence rather than in parallel.

Solution:

Move the sleep(20) statement to before the lock is removed (actually you unlock twice so simply removing the first unlock does this).

   $fp = fopen($lock_file_name, "c");

   if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
       echo "GOT LOCKn";
       /** this time window allows you to run another parallel script to prove the locking mechanism works **/
       sleep(20); 
   } else {
       echo "Couldn't get the lock!n";
   }

   flock($fp, LOCK_UN);    // release the lock
   fclose($fp); 
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement