Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP flock() alternative

Tags:

php

locking

flock

PHP's documentation page for flock() indicates that it's not safe to use under IIS. If I can't rely on flock under all circumstances, is there another way I could safely achieve the same thing?

like image 797
Matty Avatar asked Aug 06 '11 14:08

Matty


People also ask

What is flock PHP?

flock() function in PHP The flock() function locks or releases a file. The function returns TRUE on success and FALSE on failure.

What is the use of flock function?

flock() allows you to perform a simple reader/writer model which can be used on virtually every platform (including most Unix derivatives and even Windows). The lock is released also by fclose(), or when stream is garbage collected.

What is Lock_nb?

LOCK_NB means non-blocking. Usually when you try to lock a file, your PHP script execution will stop. The call to flock() then blocks it from resuming. It does so until a concurrent lock on the accessed file is removed.

Which of the following PHP function is used to make a user locked out from a website?

php") . ". lock"); if (! tryLock()) die("Already running.


2 Answers

There is no alternative available to safely achieve the same under all imaginary possible circumstances. That's by design of computer systems and the job is not trivial for cross-platform code.

If you need to make safe use of flock(), document the requirements for your application instead.

Alternatively you can create your own locking mechanism, however you must ensure it's atomic. That means, you must test for the lock and if it does not exists, establish the lock while you need to ensure that nothing else can acquire the lock in-between.

This can be done by creating a lock-file representing the lock but only if it does not exists. Unfortunately, PHP does not offer such a function to create a file in such a way.

Alternatively you can create a directory with mkdir() and work with the result because it will return true when the directory was created and false if it already existed.

like image 84
hakre Avatar answered Sep 30 '22 01:09

hakre


You can implement a filelock - unlock pattern around your read/write operations based on mkdir, since that is atomic and pretty fast. I've stress tested this and unlike mgutt did not find a bottleneck. You have to take care of deadlock situations though, which is probably what mgutt experienced. A dead lock is when two lock attempts keep waiting on each other. It can be remedied by a random interval on the lock attempts. Like so:

// call this always before reading or writing to your filepath in concurrent situations
function lockFile($filepath){
   clearstatcache();
   $lockname=$filepath.".lock";
   // if the lock already exists, get its age:
   $life=@filectime($lockname);
   // attempt to lock, this is the really important atomic action:
   while (!@mkdir($lockname)){
         if ($life)
            if ((time()-$life)>120){
               //release old locks
               rmdir($lockname);
               $life=false;
         }
         usleep(rand(50000,200000));//wait random time before trying again
   }
}

Then work on your file in filepath and when you're done, call:

function unlockFile($filepath){
   $unlockname= $filepath.".lock";   
   return @rmdir($unlockname);
}

I've chosen to remove old locks, well after the maximum PHP execution time in case a script exits before it has unlocked. A better way would be to remove locks always when the script fails. There is a neat way for this, but I have forgotten.

like image 20
Lars Avatar answered Sep 30 '22 01:09

Lars