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

     I am writing some code that forks off children when clients connect and at certain times needs exclusive access to resources. I don't want a client to sit and wait forever if another process hangs onto a resource for a long period of time. The idea is attempt to lock, if unsuccessful, send the client a timeout message.
     Below is what I have come up with as a solution, I would like to know if anybody has any comments or suggestions as to a better solution:
sub Sem_P { my $x; open(LOCK, ">$lockfile"); #Attempt to get a lock for($x = 0; ($x = $Lock_Tries) && !flock(LOCK, LOCK_EX | LOCK_ +NB); $x++) { #Sleep using select for a granularity #of less than 1 second select(undef, undef, undef, $Lock_Timeout); } return ($x =< $Lock_Tries); }

Replies are listed 'Best First'.
Re: Non-Blocking Semaphore
by KM (Priest) on Aug 25, 2000 at 23:11 UTC
    Have you tried using alarm()?

    # untested with your particular situation, but should be a guide. eval { local $SIG{ALRM} = sub { die "lock\n" }; # NB: \n required alarm 5; flock(LOCK, LOCK_EX | LOCK_NB); alarm 0; }; if ($@) { die unless $@ eq "lock\n"; } else { # keep going }

    Cheers,
    KM

      That would do the trick. But only if timing isn't critical as alarm isn't precise (like sleep) and if your timeout is always some number of whole seconds.

      /\/\averick

        Time::HiRes offers ualarm if you want and your OS has the command available. You can import their alarm as well.

        Yet another solution on systems which support SysV semantics (Linux does, Windows probably doesn't...) is to use IPC::Semaphore.

RE (tilly) 1: Non-Blocking Semaphore
by tilly (Archbishop) on Aug 25, 2000 at 23:31 UTC
    Well Simple Locking was my answer to a similar problem. Though I didn't worry about sub-second timeouts because nightly crons generally don't care.