PHP – upgraded fopen and fclose that allow working in parallel with files by using file locks

Since you are a successful web developer, or on your way there, your websites will be getting many visitors at the same time. If your PHP scripts need to modify files as part of their normal functioning, you will encounter the problem of two scripts trying to modify the same file at the same time. The classic solution offered by PHP is to work with file locks. The flock function in PHP is a great start, but unfortunately if somebody else is already using your file, the story ends there. You need to add some extra code to keep retrying to use the file, until the file lock is released. Furthermore, you might have already programmed significant parts of your code using fopen and fclose, and now you would need to change them to use flock.

I’ve created the functions flockopen and flockclose as a solution to this problem. You can use them in the same way you would use fopen and fclose, so you can simply use the “find and replace” tool, and change “fopen” to “flockopen”, and “fclose” to “flockclose”. They handle the file locks for you, so that it now allows your scripts to try to access the files in parallel, and they also patiently wait to get a file lock, in case another script already has a file lock on your desired file.

You can customize how often they retry obtaining a lock on file, in case somebody else has a lock on it, by changing the $sleep argument. You can also change the lock type by using the $lock_operation argument.

function flockopen($filepath, $mode, $lock_operation = null, $sleep = 1000)
{
	if ($mode == 'w') $mode = 'c';
	if (is_null($lock_operation))
	{
		if ($mode == 'r') $lock_operation = LOCK_SH;
		else $lock_operation = LOCK_EX; // $mode == 'w' and other cases
	}
	
	$max_execution_time = ini_get('max_execution_time');
	$file_handler = fopen($filepath, $mode);
	if ($file_handler)
	{
		for ($i = 1; $i <= $max_execution_time; $i++)
		{
			if (flock($file_handler, $lock_operation)) 
			{	
				if ($mode == 'c') ftruncate($file_handler, 0);
				return $file_handler;
			}
			else usleep($sleep);
		}
	}
	
	$error = "\n"."Could not open file with lock (MODE '".$mode."'): ".$filepath;
	error_log($error);
	die($error);	
}

function flockclose($file_handler)
{
	flock($file_handler, LOCK_UN);
	fclose($file_handler);
}

One Response to PHP – upgraded fopen and fclose that allow working in parallel with files by using file locks

  1. object0r says:

    This is completely wrong. Please do not use this:

    1) $sleep parameter is pointless. If you don’t use LOCK_NB lock, the flock function just blocks there until it gets the lock.
    2) for ($i = 1; $i <= $max_execution_time; $i++) – This makes sense only if $sleep is 1000.
    3) usleep takes input as microseconds. You assume ms.
    4) What happens if max_execution_time is 0 ? (php cli – very common)
    5) Lock operation is pointless, you can derive it from $mode.
    6) Maybe its be but die() in a function is not a good idea.

Leave a Reply

Your email address will not be published. Required fields are marked *

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close