Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

About PHP parallel file read/write

Tags:

php

Have a file in a website. A PHP script modifies it like this:

$contents   = file_get_contents("MyFile");

// ** Modify $contents **

// Now rewrite:
$file       = fopen("MyFile","w+");
fwrite($file, $contents);
fclose($file);

The modification is pretty simple. It grabs the file's contents and adds a few lines. Then it overwrites the file.

I am aware that PHP has a function for appending contents to a file rather than overwriting it all over again. However, I want to keep using this method since I'll probably change the modification algorithm in the future (so appending may not be enough).

Anyway, I was testing this out, making like 100 requests. Each time I call the script, I add a new line to the file:


First call:

First!

Second call:

First!

Second!

Third call:

First!

Second!

Third!

Pretty cool. But then:

Fourth call:

Fourth!

Fifth call:

Fourth!

Fifth!


As you can see, the first, second and third lines simply disappeared.

I've determined that the problem isn't the contents string modification algorithm (I've tested it separately). Something is messed up either when reading or writing the file.

I think it is very likely that the issue is when the file's contents are read: if $contents, for some odd reason, is empty, then the behavior shown above makes sense.

I'm no expert with PHP, but perhaps the fact that I performed 100 calls almost simultaneously caused this issue. What if there are two processes, and one is writing the file while the other is reading it?

What is the recommended approach for this issue? How should I manage file modifications when several processes could be writing/reading the same file?

like image 413
Voldemort Avatar asked Aug 21 '14 01:08

Voldemort


1 Answers

What you need to do is use flock() (file lock)

What I think is happening is your script is grabbing the file while the previous script is still writing to it. Since the file is still being written to, it doesn't exist at the moment when PHP grabs it, so php gets an empty string, and once the later processes is done it overwrites the previous file.

The solution is to have the script usleep() for a few milliseconds when the file is locked and then try again. Just be sure to put a limit on how many times your script can try.

NOTICE:

If another PHP script or application accesses the file, it may not necessarily use/check for file locks. This is because file locks are often seen as an optional extra, since in most cases they aren't needed.

like image 172
Nicholas Summers Avatar answered Sep 26 '22 23:09

Nicholas Summers