No, truncating a file does not cause any locks on it to be released. The pitfall Dominus was referring to here was that if the operation you're trying to lock is an edit of the file then this won't work since the act of opening it causes an 'edit' before you even ask for a lock. In the original poster's case though that's not a problem, since the lock file is being used as a semaphore to serialise access to a code section - the lock file will never have any contents to get clobbered. Looks good to me.
| [reply] [Watch: Dir/Any] |
No, truncating a file does not cause any locks on it to be released.
Well actually I didnt say the lock would be released, just that the effect would be the same. But that was based on the presumption that the write behaved like an unlink, but your comment about the truncate (assuming it is correct, which on reflection I do) would invalidate that point anyway. (just explaining myself :-)
The pitfall Dominus was referring to here was that if the operation you're trying to lock is an edit of the file then this won't work since the act of opening it causes an 'edit' before you even ask for a lock.
The pitfall is worse when cross platform compatibility is considered. On Win32 trying to open a file for write that is locked is an 'Access is denied' error.
In the original poster's case though that's not a problem, since the lock file is being used as a semaphore to serialise access to a code section - the lock file will never have any contents to get clobbered. Looks good to me.
Ok, I can see your point about Unix. I still would say its bad code though, not only because of the Win32 issue, but because it just seems like a sloppy habit to get into. If you are going to utilize locking semantics, try to utilize the whole thing I would say. Also, one day you might change the semaphore file to actually hold data, then you might find the habit bites you. :-) But for me I can't do things like this anyway, so maybe I'm just rationalizing the necessity.
Since you seem to know about this a bit, maybe you can explain something: it seems to me that there is no way to avoid a race condition if you want to have two processes that can do read/write on the same file on unix. Im assuming the logic would look like something like this
my $fh;
LOCK:{
open $fh,"+<",$file or
open $fh,"+>",$file or last;
flock($fh,LOCK_EX|LOCK_NB) or last;
}
$fh or die "$!";
Isnt there a race condition when there is no file? The two process both see no file to read, and go to open if with write semantics, the first opens it even maybe gets the lock, then the second comes along, and does the same thing, truncating the file and then whether the lock fails or not the file state become indeterminate. Am I understanding this correctly? Does this mean that the only way to safely do this is to use a semphore file in the first place?
Anyway, thanks for the heads up about truncate.
---
demerphq
<Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
| [reply] [Watch: Dir/Any] [d/l] [select] |
use Fcntl qw(:flock);
open(FILE, ">sem.lck") or die $!;
print "Opened file\n";
flock(FILE, LOCK_EX) or die $!;
print "Got lock\n";
sleep(10);
close(FILE);
I do exactly this on Win32 all the time.
You're right, there is a potential race condition if you want to lock the file you're editing and you need to create it if it doesn't exist. The way around that is to use sysopen like this:
sysopen(FILE, $path, O_RDWR|O_CREAT|O_EXCL) or die $!;
The O_CREAT flag specifies that the file should be created if it does not exist and the O_EXCL specifies that the create should fail if the file does already exist. But this quickly gets complicated because you need to use one form if the file doesn't exist and another if it does. That's why it is so much simpler to use a separate file for locking than the file you're editing.
| [reply] [Watch: Dir/Any] [d/l] [select] |