in reply to Re (tilly) 1: Flock Feedback
in thread Flock Feedback

First off, the config stuff is already externalized. I chose not to include that code because I didn't want to confuse the actual question. (Doing my homework and providing the simplest case. :} )

I think I see your point, but am not sure I followed the solution. I think you said, instead of opening/flocking/closing the data file twice, do something like this:

Is that right? (I'm just making sure I understand the basic logic before I dive into the code.)

-f

Update: Okay; I think I get it. Two follow ups:

Replies are listed 'Best First'.
Re (tilly) 3: Flock Feedback
by tilly (Archbishop) on Feb 25, 2001 at 09:41 UTC
    Close. Your traditional flock will either be blocking or non-blocking. If you only set the LOCK_EX flag, it will block by default, therefore when you try to get the lock it will wait indefinitely.

    If this is not what you want, then you should set the LOCK_NB flag as well, and poll at a specified interval a specified number of times before giving up. (You can set an alarm, but Perl's signal handling is not very good so I would not recommend doing that.)

    The portable way to get those constants is to

    use Fcntl qw(:flock); # time passes foreach (1..10) { $is_locked = flock(FH, LOCK_EX | LOCK_NB); last if $is_locked; ### Or gets both flags sleep 1; } # Test $is_locked here
    See the longer example for the full semantics of how to do the open, etc. (There I am locking a sentinel...)

    UPDATE
    In the above FH is a filehandle that has already been opened. As for the other question, yeah that module will solve the problem. But everything that I said about locking will also hold when you want to start playing games with reading and writing other kinds of data files as well...

    UPDATE 2
    OK, if you want to do this explicitly for a sentinel, here is some untested code:

    use Carp; use Fcntl qw(:flock); sub open_sentinel { my $lock_file = shift; my $fh = do {local *FOO}; # Old trick open ($fh, "> $lock_file") or die "Cannot write $lock_file: $!"; my $is_locked; foreach (1..10) { $is_locked = flock($fh, LOCK_EX | LOCK_NB); last if $is_locked; select (undef, undef, undef, 0.01); } return $is_locked ? $fh : undef; }
    This will wipe out the file (hence it is only useful to use on a sentinel file). To get the lock just try to grab. The variable will only be defined if you got the lock, and the lock is freed when the variable is destroyed. (So you can enter a routine, ask for a lock, if you get it then proceed, if you don't then exit immediately.)

    The above example tries 10 times, one hundredth of a second apart.