Thiemo Mättig

Thiemo Mättig

I'm currently cleaning up the backend code of this weblog, to be able to finally switch this site to HTML 5 and UTF-8. Some of the PHP code I found dates back to 2001. Some files still relied on register_globals, which I disabled years ago. But the most interesting detail I found is a repeating pattern of code in which I used flock wrong for years and years.

This is what I did over and over again:

$fp = fopen( $filename, 'wb' );
flock( $fp, LOCK_EX );
fwrite( $fp, $data );
This is wrong. Why? Because this locks the file after it was truncated to zero length! If two users run into a deadlock situation and the lock fails, the contents of the file are gone!

This is how it should be done:

$fp = fopen( $filename, 'r+' );
flock( $fp, LOCK_EX );
rewind( $fp );
fwrite( $fp, $data );
ftruncate( $fp, ftell( $fp ) );
The file is opened in »read and write« mode, which means it is not truncated. The lock may fail, and is now allowed to fail. The file will still be the same as before. If the lock succeeds, the script can be sure it does have exclusive access to the file for all following operations. These operations include rewinding the file pointer to the start of the file, and truncating the file to it's new length. The rewind is necessary when the file pointer was moved by other read or write operations in the same script. I like to do this just to be sure, even if it's not necessary in trivial cases like my example here. The truncation is necessary when the new file contents are smaller than the file was before.
Und was ist wenn flock() FALSE zurückliefert?
T$
Ich bin mir nicht ganz sicher. Ich glaube, das kann gar nicht passieren, so lange man LOCK_NB ("nicht blockieren") nicht verwendet. Das Skript stirbt einfach mit einem Timeout.
Thiemo
In den meisten heutigen Fällen würd ich auch vermuten daß das so ist, fragt sich nur ob das immer so ist (z.B. bestimmte Betriebs- und Dateisysteme). Gibt jedenfalls recht viel Code der auch mit blockierendem Aufruf das Ergebnis prüft, aber nirgendswo eine Erklärung dazu...
T$

Kommentare zu diesem Beitrag können per E-Mail an den Autor gesandt werden.

[ < Zurück zur Übersicht ]