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

I'm writing a module that using flock() as part of its filehandling. (I'm on Solaris, if it makes any difference.) Like a good Perlmonkey, I'm writing a test, seeing it fail, writing some code, seeing it pass. Except, I'm running into a problem. (Assume the variables are all declared and set appropriately.)
001_sometest.t -------------- use_ok( $CLASS ); my $obj = $CLASS->new( filename => $logfile, ); isa_ok( $obj, $CLASS ); ok( -e $logfile, "$CLASS created logfile" ); open my $fh, '>>', $logfile or die "Cannot open '$logfile' for appending: $!\n"; my $rc = flock( $fh, LOCK_EX | LOCK_NB ); ok( !$rc, "Cannot flock $logfile" );

The point is that new() will open $filename for appending, then flock it with LOCK_EX. All this is happening successfully. Except, I don't seem to be able to test that I got the flock correctly. Is this because I'm trying to test a process-level lock within the same process? How would you test it? I don't want to whip out Proc::Background . . .


The Perfect is the Enemy of the Good.

Replies are listed 'Best First'.
Re: Testing if your code successfully flocked
by Joost (Canon) on Apr 26, 2005 at 15:04 UTC
    My flock() manpage (linux) says (emphasis mine):
    Locks created by flock() are associated with a file, or, more precisely, an open file table entry. This means that duplicate file descriptors (created by, for example, fork(2) or dup(2)) refer to the same lock, and this lock may be modified or released using any of these descriptors. Furthermore, the lock is released either by an explicit LOCK_UN operation on any of these duplicate descriptors, or when all such descriptors have been closed.

    A process may only hold one type of lock (shared or exclusive) on a file. Subsequent flock() calls on an already locked file will convert an existing lock to the new lock mode.

    So you'll probably have to run some kind of external process to test the lock. Or you could decide to trust that flock() works.

    Also of interest - from the perlfunc flock() manpage:

    On systems that support a real flock(), locks are inherited across fork() calls, whereas those that must resort to the more capricious fcntl() function lose the locks, making it harder to write servers.
Re: Testing if your code successfully flocked
by Transient (Hermit) on Apr 26, 2005 at 15:00 UTC
    flock seems to return true/false rather than a system return code (which is what I'm assuming you're expecting - and also what I'd expect).

    I made a test where I flocked, printed the rc, slept for 1000. Ran this in the background and then ran again. First process got 1, second got 0. This was on AIX, BTW. I'm assuming you're just concerned about why it's failing?
Re: Testing if your code successfully flocked
by ikegami (Patriarch) on Apr 26, 2005 at 15:02 UTC

    Works for me in FreeBSD and Windows:

    use strict; use warnings; use Fcntl ':flock'; open my $fh1, '>>', 'moo' or die "Cannot open moo for appending (1): $!\n"; print(flock($fh1, LOCK_EX | LOCK_NB) ? 1 :0, "\n"); open my $fh2, '>>', 'moo' or die "Cannot open moo for appending (2): $!\n"; print(flock($fh2, LOCK_EX | LOCK_NB) ? 1 :0, "\n");
    1 0
      On Solaris, I get:
      $ perl a 1 1
      I think Joost is right, which sucks rocks. *sighs*

      The Perfect is the Enemy of the Good.

Re: Testing if your code successfully flocked
by salva (Canon) on Apr 26, 2005 at 15:10 UTC
    Is this because I'm trying to test a process-level lock within the same process?

    I think so!

    to test, fork a new process, and try to open and flock the same file both in the child and in the parent with the NB option, check that one succeeds and the other fails.

    Other way, fork 10 processes, make all them wait some random seconds, flock the file, read some number for it, sleep other some random seconds, write the number incremented. On the parent wait for all the processes to exit, check that the number in the file is 10.

Re: Testing if your code successfully flocked
by halley (Prior) on Apr 26, 2005 at 16:30 UTC
    Remember, even once you have a test working, that flock() is not infallible, that there are no warranties or guarantees that the lock will be enforced or visible to any or all systems able to see that filesystem. NFS, SMB, or even just different architectures may fail to honor a flock().

    --
    [ e d @ h a l l e y . c c ]