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

Hello,

I have a CGI Perl script that updates a data file when a user submits a web form. The script uses flock to exclusively lock a secondary file to prevent the data file from being updated by more than one user at a time. I believe this has worked well for some time now.

However, I'm beginning to suspect that occasionally (maybe when the web server is busy) the flock call fails.

Unfortunately, I am not trapping for an error condition each time I call flock because I test for the capability at the beginning of the script. I will soon change this to always test for failure. Then I will know for sure if it ever fails.

In the meantime, reading through the documentation for flock, the only reason I can see for flock to fail is if the operating system doesn't support file locking. Otherwise, unless you tell it not to, it waits indefinitely.

Are there occasions where flock will not wait indefinitely but will instead fail?

Any help would be greatly appreciated.

Richard

  • Comment on Can flock occasionally fail on systems that support file locking?

Replies are listed 'Best First'.
Re: Can flock occasionally fail on systems that support file locking?
by Zaxo (Archbishop) on Jul 10, 2003 at 14:52 UTC

    man 2 flock lists only one error condition:

    EWOULDBLOCK The file is locked and the LOCK_NB flag was selected.
    As cfreak suggests, some process (maybe yours) already has the lock.

    Seeing your reply to cfreak, yes, a cgi environment may well be running more than one instance of your script. If LOCK_NB is not set, one instance will wait until the other lets go.

    Update: Calling flock as flock FH, $opts or warn $!; will tell you what error is set. I don't understand why LOCK_NB is necessary to you. For most purposes, the blocking form is preferred. The effect is to sleep until the file is available.

    After Compline,
    Zaxo

      Thank you for your reply.

      Yes, I have read the man pages but am wondering if in practice there are occasions when there are other reasons for flock to fail.

      "...If LOCK_NB is not set, one instance will wait until the other lets go."

      This is what I expect to happen and how I have designed the script to work.

      Unfortunately, I'm getting reports that occasionally a submission isn't making it to the data file and I'm wondering if flock is failing in these cases, thus allowing the data file to be opened, written to and closed at the same time by more than one user.

      Adding error handling around flock might confirm my suspicion -- but I also wonder if flock occasionally succeeds for a second simultaneous submission because of lock inheriting or something even more mind boggling.

      Richard

Re: Can flock occasionally fail on systems that support file locking?
by cfreak (Chaplain) on Jul 10, 2003 at 14:34 UTC

    Is it possible that some other program (that doesn't respect the flock) is accessing it?

    I would make sure, as well as checking the flock call for failure like you stated :)

    Lobster Aliens Are attacking the world!
      Thank you for your reply.

      No, this is the only program that knows about the data file. I have read about this in the various books and online help and verified this.

      I have another idea, though:

      I wonder if it's possible for Perl or the Web server to occasionally have a new instance of the same Perl script inherit the locks of a previous instance of the script. I got this idea by reading about how forking inherits locks.

      For example, let's say 10 people submit the same form at the same time. Each of the 10 submissions starts a new instance of the same Perl script. The Perl script uses flock to lock a secondary file. Is it possible for Perl to occasionally decide that one instance of the script should inherit the locks of another? If so, then the locking has been defeated.

      Richard

        That's not possible. Each instance of perl is independent of the other. Unless you use the fork function, it's not gonna happen.

        MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
        I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
        ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Can flock occasionally fail on systems that support file locking?
by danb (Friar) on Jul 10, 2003 at 17:01 UTC

    Our experience is that 5.8.0 has had some changes with regard to locking. In 5.6, you were always gauranteed an flock, unless there was some monumental fatal error -- it just took a long time sometimes.

    In 5.8, the new functionality seems to be that if it can't get the lock in a reasonable time-frame, it throws EINTR, and then wants you to try again later.

    For the Interchange project, here is what they did (it seems to solve the problem for us):

    sub flock_lock { my ($fh, $excl, $wait) = @_; my $flag = $excl ? $flock_LOCK_EX : $flock_LOCK_SH; if ($wait) { my $trylimit = $Vend::Cfg->{Limit}{file_lock_retries} || 5; my $failedcount; while ( ! flock($fh, $flag) and $failedcount < $trylimit ) { $failedcount++; select(undef,undef,undef,0.05 * $failedcount); } die "Could not lock file after $trylimit tries: $!\n" if ($fai +ledcount == $trylimit); return 1; } else { if (! flock($fh, $flag | $flock_LOCK_NB)) { if ($!{EAGAIN} or $!{EWOULDBLOCK}) { return 0; } else { die "Could not lock file: $!\n"; } } return 1; } }
    -Dan
      Thank you for this information.

      According to the ISP's FAQ, the version of Perl on the Web server is 5.00503-2.

      However, this script is used on many web sites so I now have more motivation to put in error handling around the flock calls to handle the case where 5.8 is installed and flock times out.

      Thank you!

      Richard

Re: Can flock occasionally fail on systems that support file locking?
by dws (Chancellor) on Jul 10, 2003 at 16:19 UTC
    However, I'm beginning to suspect that occasionally (maybe when the web server is busy) the flock call fails.

    If you're unable to show us code (or even if you are), it sounds like this calls for a basic debugging technique: strip extraneous stuff out, and see if you can come up with a small example that demonstrates the problem. Quite often, the act of removing stuff that you think isn't part of the problem either reveals that some of it really is. Or, the real problem is laid bare.

    Since you're working with CGIs, that might mean figuring out some way of programmatically driving the web server (e.g., by multiple LWP clients).

      Thank you for your reply.

      Unfortunately, I am not able to do much debugging because this is happening on a live project on a customer's web server which belongs to an ISP. My customer doesn't want me to make debugging changes to the script while the project is going on.

      So far, I'm unable to reproduce the problem on my own web servers. This leaves me to discuss theory and such, which is what brought me here.

      What makes it more difficult is it appears to happen when there a lot of simultaneous submissions. I will ask but I don't think I will even be able to copy a test script to their web server and test many simultaneous form submissions.

      I guess I could show some code, but I'm looking to get a better understanding of flock -- beyond all that is available online and in the Perl Cookbook and Programming Perl books.

      Richard

Re: Can flock occasionally fail on systems that support file locking?
by perlplexer (Hermit) on Jul 10, 2003 at 16:37 UTC
    "Are there occasions where flock will not wait indefinitely but will instead fail?"

    Yes.

    • flock() is not supported. If I remember correctly, in such a case the script bombs unless you trap the error.
    • when you use LOCK_NB and the file is already locked (as others already pointed out).
    • when a signal is received while flock() is blocked.
    --perlplexer
      perlplexer,

      Thank you for your reply.

      Could you explain what you mean by "when a signal is received while flock() is blocked"?

      Richard

        Suppose you have two processes that work with the same lock file and each take 5 minutes to complete. One process starts up, locks the file, and then proceeds to do whatever it's designed to do. A second instance of this process is then started by some other user a minute later. This instance will call flock(), which will block and wait until the first instance releases the lock. If during this time this second instance is interrupted by a signal; e.g, ALRM, INT, etc., flock() will return and $! will be set to "Interrupted system call" (IIRC). If your program does not check the return value and continues to run, it'll clobber the file.

        --perlplexer