Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello everyone,

Can anyone pleaaase tell me what the most secure method of flocking is, or know of? I'm so lost, and going out of my mind :(

I started a thread here, and I was so thankful that mirod had answered me, and I thought my troubles were over :) Unfortunately I'm still having trouble with this. I left my last post there on March 12th, which I think has gotten lost with all the other posts, since no one has answered, and I don't know how to bump it up :)

I've been trying to read everything I could here and have managed to find these:

Everyone seems to have their own ways of doing this, and after reading and trying to understand, I've stayed on with KM's way of file locking. But as I said with my last post it still does not work.

What could I possibly be doing wrong? I also use this method as well.. is this wrong?

Example::

$SEMAPHORE = $tempfile . '.lck'; open(S, ">$SEMAPHORE") or die "$SEMAPHORE: $!"; flock(S, LOCK_EX) or die "flock() failed for $SEMAPHORE: $!"; open (TEMP, ">$tempfile") or die "Can't open $tempfile: $!"; open (FH, "$file") or die "Can't open $file: $!"; while (<FH>) { ## do_something; } close FH; close TEMP; rename($tempfile,$file); close S;
From what I understand this method should be locking all the files that are being read/written to? or Have I misunderstood? Both examples I have used still wipes my file clean every so often :(

Sorry for the long post, I feel like an idiot :(
Thanks so much

PS.. Is there a way to search the posts here on the monastery? Using the search box that appears at the tops of the pages just locates the perl man explainations.

Replies are listed 'Best First'.
Re: flock() ..I really need a hand .. please :)
by AgentM (Curate) on Mar 20, 2001 at 10:01 UTC
      Hello, Thank you all for your wisdom. I do appreciate the help & tips:

      a, just to clarify, all the files were using the same $SEMAPHORE file, so any instance of $tempfile getting written to, $tempfile was locked. I double checked the locks as well, by placing the sleep method KM had discussed. The lock was working when I had checked. (Using the names "$tempfile" and "$file" were actually just examples, in the code the real file names are placed instead.)

      I dunno, I've gone over this a bizillion times and double checked everywhere, and it only happens once in a while where the file gets wiped. I really like KM's method because it does make sense, and that's probably the first time flock() actually makes sense to me. I would guess it's better than when I first began using just flock(FILE,2);

      I'll keep plunking away at it, and hopefully I'll get something that will work. Also thanks for the tip to debug "rename" I'll add that right away.

      AgentM Thank you for letting me know about the module File::CounterFile I went and took a look, it looks interesting enough, but it says under Bugs that it uses the flock(2); method. This was something I was trying to avoid. What are your feeling on that?

      Well Thanks again, I do appreciate the help :-)

      PS.. Thanks turnstep that search was great!!

        The "bug" reports that flock is not entirely cross-platform (it's emulated decently on most systems which don't natively support flock but do support advisory locking). That simply means the target system needs to support flock (advisory locks). The report suggests a File::Lock module which doesn't exist (perhaps a good idea).
        AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
Re: flock() ..I really need a hand .. please :)
by turnstep (Parson) on Mar 20, 2001 at 07:41 UTC
    PS.. Is there a way to search the posts here on the monastery? Using the search box that appears at the tops of the pages just locates the perl man explainations.

    Check out the woefully unpublicized Super Search

    :)
Re: flock() ..I really need a hand .. please :)
by a (Friar) on Mar 20, 2001 at 09:59 UTC
    Well, this probably won't be helpful, but ...
    flock is not going to save you if the 'other' apps won't play nice. Likewise, unless all your apps respect the SEMAPHORE flag (e.g.:
    while ( -s $SEMAPHORE ) { print STDERR "lock found waiting\n" if $debug > 10; sleep 5; }
    flocking it won't do much. Of course, this implies that $SEMAPHORE is a well known name (/tmp/myapp.lck), not /tmp/mlock$$.lck - unless other versions can predict the name and check if it exists, (I'm guessing $file is the useful name and the file that gets 'wiped' now and then) your lock/semaphore isn't going to help. It seems your code would allow 2 instances to mess w/ $file if they each had different $tempfile instances. It should be that they have one $SEMAPHORE to work w/, check the existence of, etc.

    Sorry, I don't recall your other posts, but you might also do your self some good by having the 'rename' preceeded by a debug "about to rename $tempfile to $file (I'm $this instance)" so you can see who is doing the wiping in hopes of pinpointing where your lock/semaphore goes a stray. As I read it, though your flocking isn't really giving you exclusive access for multiple instances of that code, or for anybody else, unless they're using the same $tempfile.

    a

      I think I've found were I am going wrong. Thanks a for your effort of a reply, after re-reading a few times everything you said, I am wrong, my $SEMAPHORE file is not the same all the time.

      I think what I was doing was concentrating so hard on KM's example of renaming the "locked file" the same name as the file getting written to, that I neglected to think of the first lesson I learned about flock(). That flock() works if the file in question shares the same locking functions throughout the code.

      What I think I'm doing wrong, and please correct me if I'm not right, but when I was reading file A to spit out the contents, I was using a shared lock (LOCK_SH) and I named my $SEMAPHORE file the same name as file A but with .lck at the end. So sometime during the code I had to write to my TEMP file B and named my $SEMAPHORE file "file B.lck" So in essence the two $SEMAPHORE file names were different.

      Is this were my mistake lays? If I'm assuming correctly I have to name my TEMP $SEMAPHORE file name the same as "file A" Does this make sense so far? I hope I'm explaining myself correctly :) Here is a small example of what I was doing wrong I think:

      ########################################## # Reading $Afile = "A.txt"; $SEMAPHORE = $Afile . '.lck'; open(S, ">$SEMAPHORE") or die "$SEMAPHORE: $!"; flock(S, LOCK_SH) or die "flock() failed for $SEMAPHORE: $!"; open (FH, "$Afile") or die "Can't open $Afile: $!"; while (<FH>) { ## do_something; } close FH; close S; ##########################################- wrong way # Writing $Bfile = "B.txt"; $SEMAPHORE = $Bfile . '.lck'; ### Using $Bfile as $SEMAPHORE file name open(S, ">$SEMAPHORE") or die "$SEMAPHORE: $!"; flock(S, LOCK_EX) or die "flock() failed for $SEMAPHORE: $!"; open (TEMP, ">$Bfile") or die "Can't open $Bfile: $!"; open (FH, "$Afile") or die "Can't open $Afile: $!"; while (<FH>) { ## do_something; } close FH; close TEMP; rename($Bfile,$Afile); close S; ########################################## -right way? # Writing $Bfile = "B.txt"; $SEMAPHORE = $Afile . '.lck'; ### Should be using $Afile as $SEMAPHORE + file name etc..
      So am I safe to assume that this would wipe my file contents? Because when one process opened my main file for reading my other process may have been re-writing the TEMP file then renaming it, and my main file was not flocked. I think I'm confusing myself :/ but I hope I'm right.??!

      Thank you again, and thanks AgentM for the reply too. I'll give that module a try :-)