Correct file locking techniques

From: Robert TV (ducott_at_hotmail.com)
Date: 06/27/04


Date: Sat, 26 Jun 2004 23:46:17 GMT

Hi, I am asking foir advice on which form of code i've written below is the
correct and safe way to lock a file. I've done some reading on" use Fcntl
qw(:DEFAULT :flock);" and I understand the basics. I've also read back on
many posts regarding file locking and there seems to be much debate. For
this code, I simply want to increase a value.

#!/usr/bin/perl

use Fcntl qw(:DEFAULT :flock);
use CGI::Carp qw(fatalsToBrowser);

open (NUMBER, "<number.txt") or die "Can't open file: $!";
  flock (NUMBER, LOCK_EX) or die "Can't lock file: $!";
  $value = <NUMBER>;
close(NUMBER);

$value = $value++;

open (NUMBER, ">number.txt") or die "Can't open file: $!";
  flock (NUMBER, LOCK_EX) or die "Can't lock file: $!";
  print NUMBER $value;
close(NUMBER);

The above code seems to work ok. My question is when the first user locks
and reads the file, does the locking prevent other users from reading the
file? The $value is then increased and printed back to the file.

Another concern of mine is ... User#1 locks file, reads file value, then
close and releases lock. While User#1 is writing the new value back to the
file, another user came and read the unlocked file BEFORE the value was
increased. So he gets the same value as User#1. User#2 then increases the
value and writes the same data as User#1. In the end, the locking technique
failed ... am I right?

Another method I came up with is locking and entire read/write session
within a what I will call "parent lock" Here is the code:

#!/usr/bin/perl

use Fcntl qw(:DEFAULT :flock);
use CGI::Carp qw(fatalsToBrowser);

open (PARENT, "<locker.txt") or die "Can't open file: $!"; #an empty file
  flock (PARENT, LOCK_EX) or die "Can't lock file: $!";

open (NUMBER, "<number.txt") or die "Can't open file: $!";
  flock (NUMBER, LOCK_SH) or die "Can't lock file: $!";
  $value = <NUMBER>;
close(NUMBER);

$value = $value++;

open (NUMBER, ">number.txt") or die "Can't open file: $!";
  flock (NUMBER, LOCK_SH) or die "Can't lock file: $!";
  print NUMBER $value;
close(NUMBER);

close(PARENT); #closes the parent lock

Now User #1 locks the parent file and moves on to the read/write session.
All other users get stuck back at the parent lock until released. I had to
use LOCK_SH for the read/write locks for some reason ... if all locks were
set to EX the program would stall. Is this technique better? Is it
effective? Or perhaps they are both ineffective?

In this next example, I don't want to increase a value, just append to the
file on a new line. So I do this:

#!/usr/bin/perl

use Fcntl qw(:DEFAULT :flock);
use CGI::Carp qw(fatalsToBrowser);

open (DATA, ">>locker.txt") or die "Can't open file: $!";
  flock (DATA,LOCK_EX) or die "Can't lock file: $!";
  print DATA "$data\n";
close(DATA);

Im going to assume that this is ok.

It's just when increasing a value that concerns me ... multipul users
reading same value when the read lock is released. Your suggestions are
greatly welcomes. TIA

Robert



Relevant Pages

  • File Locking Local Denial of Service; Impact on sendmail
    ... Any application which uses either flockor fcntlstyle locking or ... Since this attack requires a user to use their own account to lock ... fcntl() locks require the file ... File locking is used throughout sendmail for a variety of files ...
    (Bugtraq)
  • Fwd: File Locking Local Denial of Service; Impact on sendmail
    ... File Locking Local Denial of Service; Impact on sendmail ... Since this attack requires a user to use their own account to lock ... fcntl() locks require the file ...
    (FreeBSD-Security)
  • Re: Locking in C++
    ... even if the file is locked by fcntl or lockf, ... > But it's even worse than that; The locking functions provided to obtain ... > a lock operate on file descriptors, ...
    (comp.unix.programmer)
  • Re: using clustered index to optimize inserts ...
    ... I will try to explain locking in terms of Sybase docs... ... Allpages Locking: Allpages locking locks both data pages and index ... the data page is locked with an exclusive lock. ... Clustered Index: The datarows will be arranged as per the clustered ...
    (comp.databases.sybase)
  • Re: UW imap-2006b: 64 bit problem
    ... UW imapd is obliged> to do considerable more work on SVR4 systems than it does on BSD and> Linux systems which offer flock() locking as an alternative to POSIX> locking. ... IEEE Std 1003.1-1988 requires that all fcntl() locks associated with a file for a given process are removed when *any* file descriptor for that file is closed by that process. ... Put another way, before any library routine opens a file, it must be aware of what files the application and any other libraries have open and locked; otherwise the library routine will remove the lock unexpectedly when it closes the file. ...
    (comp.mail.imap)