Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

flock(), dodgy return?

by danstuken (Novice)
on Aug 01, 2007 at 13:13 UTC ( [id://630045]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks,

I fear this may well be a FAQ or the combination of a couple of them. Forgive me if this is the case.

All I want is to lock a file. Truthfully. Its got so bad that this is the limit of my ambition. In the main I'm not a perl numpty, but this is driving my looney.

Running on an FC4 box I have the following code to reset (i.e. remove) an entry from the current user's ssh known_hosts file. I cannot get the lock to work. I have commented some of the artifacts of what I've already tried. Please guide me to enlightenment.

#!/usr/bin/perl my $host = $ARGV[0]; my $known_hosts = './kh.tt'; ##USE '>>' OTHERWISE WE WILL TRUNCATE AT open() - BEFORE WE HAVE THE L +OCK!! #do{ # print 'Error opening ssh known hosts file : ', $!, "\n"; # exit; #}unless( open KNOWN_HOSTS, ">> $known_hosts" ); open LOCK, "> $known_hosts.sem" or die "Can't open semaphore: $!\n"; ##lock the file my $lock_tries = 3; my $got_lock = 0; GETLOCK: while( $lock_tries ) { print "TRYING FOR LOCK ($lock_tries)\n"; #if( flock(KNOWN_HOSTS, LOCK_EX|LOCK_NB) ) my $ret = flock(LOCK, LOCK_EX|LOCK_NB); print "Flock ret : $ret\n"; if( $ret ) { print "GOT LOCK\n"; $got_lock = 1; last GETLOCK; } sleep(1); $lock_tries --; } do{ print 'Unable to lock known hosts file for updates', "\n"; close LOCK; exit; } unless($got_lock == 1); #open KNOWN_HOSTS_RD, "< $known_hosts"; open KNOWN_HOSTS, "+< $known_hosts" or die "Can't open data file: $!\n +"; #my @host_data = <KNOWN_HOSTS_RD>; my @host_data = <KNOWN_HOSTS>; #close KNOWN_HOSTS_RD; my $host_pattern = $host; $host_pattern =~ s/\./\\\./; my @new_data = grep(!/^$host_pattern/,@host_data); truncate KNOWN_HOSTS, 0; print KNOWN_HOSTS join("\n", @new_data); ##This releases the lock. close(KNOWN_HOSTS); close LOCK;
Many thanks for any help.

Replies are listed 'Best First'.
Re: flock(), dodgy return?
by radiantmatrix (Parson) on Aug 01, 2007 at 13:46 UTC

    Well, the first thing I note is that the constants LOCK_EX and LOCK_NB are never defined or imported. Try including use Fcntl ':flock'; to get them (see the Fcntl module docs).

    It's worth mentioning that perl would have pointed this out to you had you used strict and warnings. I know it seems like we harp on it, but use strict; use warnings; should really be part of anything you write.

    <radiant.matrix>
    Ramblings and references
    The Code that can be seen is not the true Code
    I haven't found a problem yet that can't be solved by a well-placed trebuchet
      Thank you radiantmatrix

      I'm appalled at myself. Of all the.... The code was taken from a 'test' script I wrote in parallel with the existing code to make sure everything I wanted to do worked. The 'parent' script does use strict and Fcntl ':flock'.

      Thank you again.

      Out of interest, you started with "...first thing I note..." do I have any other lurkers?

        I suspect he means he didn't look any further, since it's a big chunk of code and nothing obvious stood out.

        Update: This is not a complaint. We'd be happy to look further into it if you are still having problems.

Re: flock(), dodgy return?
by oxone (Friar) on Aug 01, 2007 at 14:21 UTC
    Hi. Wow what a mess! Try this to open a file with an exclusive lock.
    use strict; use warnings; use Fcntl qw(:DEFAULT :flock); sysopen(my $fh, 'filename', O_RDWR | O_CREAT) or die "Can't sysopen"; flock($fh, LOCK_EX) or die "Can't get lock"; print "OK - opened file with lock in place.\n";
    You don't need to use a 'semaphore' file to lock a single file. Also, it's probably best to let 'flock' do it's job, rather than putting it in a loop and trying over and over. For lots more info see the 'File Locking' section of The Camel book!
      I suspect alarm will do the trick if a timeout is desired, at least on a unix host.

        Yeah but that brings in more complexity than is really warrented in this situation, no?

      Thanks oxone,

      I agree with you, its a bit of a state - rest assured it wont end that way. The semaphore was a product of desperation. Its been the sort of week where everything has gone wrong (and its only wednesday!?) and so I was kinda scrabbling at the problem rather than calmly dealing with it.

      With regards to not using LOCK_NB, I don't think I can go that way. This script is called, eventually, from a GUI app and I'd rather not leave the user hanging on indefinitely, even if in 99.99% of cases the lock will only exist for fractions of a second. I keep coming over sysopen but have never used it - tbh open() works fine and is what all the scripts here use and I'd rather not move away from that.

Re: flock(), dodgy return?
by Corion (Patriarch) on Aug 01, 2007 at 14:28 UTC
Re: flock(), dodgy return?
by moritz (Cardinal) on Aug 01, 2007 at 13:59 UTC
    I don't know much about locks, but for testing purposes please ensure that you are on a local partition, not one mounted via nfs or other network file systems.

    NFS has notorious problems with locks, perhaps other network fs' have the same caveats.

      Definitely, played that game in a different life. *shudders*

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://630045]
Approved by Joost
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (9)
As of 2024-04-23 09:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found