Andrew Hill wrote: > $fp = fopen("/tmp/lock.txt", "w+"); > if (flock($fp, LOCK_EX)) { // do an exclusive lock > fwrite($fp, "$processName\n"); > flock($fp, LOCK_UN); // release the lock > } else { > echo "Couldn't lock the file !"; > } > fclose($fp); [...] > In this case, although process B is the second process to obtain a > lock and write its process name to the file, it is the first process > to close the file handle.
I've used flock() quite a bit in Perl, but not so much in PHP. I'm almost positive that they both use the same system calls so I think the behavior (at least under unix) is the same. In Perl, you do not have to release a lock before closing the file...the lock is automatically released on close. Newer versions of Perl automatically flush the disk buffers when releasing a lock, but it's still widely recommended that you do NOT release a lock before closing a file if you have written to it, precisely because of the race condition you pointed out. From: http://www.tcp.com/~mink/CLAM/week8.html "...Locks will dissolve when the file is closed anyway (when your process exits, if not before). If you unlock without closing, the buffer may not have been flushed before another process tries to read the file. In that case, the other process will get "old" data. There are ways around this, but the easiest is to simply not use LOCK_UN on files you are really writing to - simply close the files and release the locks that way..." Also: http://groups.google.com/groups?selm=388373bd.890334%40news.skynet.be http://groups.google.com/groups?selm=Pine.GSO.3.96.970311110353.695N-100000% 40kelly.teleport.com Of course these all apply to Perl, but I believe they could be applied to PHP as well. I wonder if this should be considered a documentation problem with the given examples. > My suspicion is that the answer to the above question is no, and as a > result, in order to be certain of correctly serialising the file > locking and output process, it would be necessary to use a separate > lockfile, which is opened and locked *before* the file to be written > to is opened, written, and then closed, after which the lock on the > lockfile can be released. I think that you will still have to do this, however, not because of the fclose() issue but because you are opening the file in write mode, which truncates it. If you were opening in append mode you would be good by just not releasing the lock before the fclose(), but since the fopen() in write mode truncates the file BEFORE the lock is requested, you're in trouble without using a separate lock file. There is a note in PHP's flock() documentation about that: "Note: Because flock() requires a file pointer, you may have to use a special lock file to protect access to a file that you intend to truncate by opening it in write mode (with a "w" or "w+" argument to fopen())." So, I'd still go with getting an exclusive lock on a separate lock file, writing to my actual file, then releasing the lock on the separate lock file... HTH -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php