Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

comp.unix.shell Re how to do file locking using bash by loe13858

VIEWS: 34 PAGES: 3

									                         comp.unix.shell: Re: how to do file locking using bash?

             Re: how to do file locking using bash?

Source: http://unix.derkeiler.com/Newsgroups/comp.unix.shell/2005−09/0550.html


From: Enrique Perez−Terron (enrio_at_online.no)
Date: 09/14/05

Date: Wed, 14 Sep 2005 04:40:13 +0200



On Wed, 14 Sep 2005 00:10:22 +0200, Heiner Steven <heiner.steven@nexgo.de>
wrote:

> Enrique Perez−Terron wrote:
>> On Mon, 12 Sep 2005 20:38:34 +0200, Heiner Steven
>> <heiner.steven@nexgo.de> wrote:
>>
>>> Enrique Perez−Terron wrote:
>>>
>>> [...]
>>>> I will not dispute the merits of mkdir or ln, but just for the fun
>>>> of it,
>>>> how can the scheme above be made safe?
>>>> Here is a probabilistic solution, I believe:
>>>> getlock() {
>>>> RANDOM=$$
>>>> while
>>>> echo $$ > lock.$$
>>>> list=( $(echo lock.*) )
>>>> count=${#list[*]}
>>>> [ $count −gt 1 ] # Contention
>>> [...]
>>>
>>> There is a time window between setting the variable
>>> "list", and checking for the value of the derived variable "count".
>>> In the time inbetween, the number of lock.* files could well
>>> have changed. If during assignment of "list" the count were
>>> just "1", but changed to "2" immediately afterwards, the
>>> subsequent "[ $count −gt 1 ]" still would indicate the lock
>>> being free, and two processes would try to acquire it
>>> at the same time.
>> But the other process that added another file after the present process
>> read the directory, cannot fail to notice the presence of more than
>> it's own file.
>
> Here is the code again, with line numbers for better
> reference:
>

Re: how to do file locking using bash?                                             1
                        comp.unix.shell: Re: how to do file locking using bash?
> 1 getlock() {
> 2 RANDOM=$$
> 3 while
> 4 echo $$ > lock.$$
> 5 list=( $(echo lock.*) )
> 6 count=${#list[*]}
> 7 [ $count −gt 1 ] # Contention
> 8 do
> 9 rm lock.$$
> 10 pid=$(<lock.pid) 2>/dev/null
> 11 if [ −n "$pid" ]
> 12 then
> 13 if [ −e /proc/$pid ]
> 14 then
> 15 return 1 # Lock is taken by others
> 16 else
> 17 rm −f lock.pid lock.$pid
> 18 fi
> 19 else
> 20 sleep $(( $RANDOM % $count ))
> 21 fi
> 22 done
> 23 ln lock.$$ lock.pid
> 24 return 0 # We got the lock
> 25 }
>
> There still is a race condition:
>
> o Assume lock.pid is a stale lock of process X, which no longer
> exist. Process A calls the function getlock(). At line 8
> we now have the following files:
> lock.X # stale, process X does no longer run
> lock.pid # stale too, link to lock.X
> lock.A # just created
>
> o Process A continues, and removes file
> lock.A (line 9)
>
> we now have the following files left:
> lock.X
> lock.pid
>
> Process A checks if process X is still running
> (line 13), and continues to line 17, where it removes
> lock.pid and lock.X
>
> Now there is no lock file left.
>
> Process A nevertheless assumes that it can acquire
> the lock.


Re: how to do file locking using bash?                                            2
                          comp.unix.shell: Re: how to do file locking using bash?

What? Does it? That wasn't my plan! I must have modified something
and spoiled my plan. It should only decide if it has the lock before
the "do" line.

No, it doesn't! After line 17 it reaches "done" (22) and goes back to
"while" (line 3).

>
> o Process B enters the function, creates lock file
> lock.B (the only lock file now),
> counts the number of lock files (1), and also
> assumes it has acquired the lock.
>

Exact, but now A creates lock.A again

> −−> At this time process A and process B both assume they
> have aquired the lock.

No, a is back in line 4 and creates lock.A, reads the directory in
line 5, and finds there are too many, and continues looping.
Since there is now another lock.pid it reads it and gets B's
pid in line 10, finds it is not stale in line 13 and
returns failure in line 15.

Notice that the holder of the lock must *not* remove its files!
When a process reach line 9, it means it has *not* gotten the
lock this time around. But we don't give up quite yet because
it could be due to stale files or due to a draw where neither
process gets the lock, and ultimately it's the sleep that
separates the winner from the looser.

> The race condition is related to the stale lock handling.
> Maybe it can be made to work if the function does not
> try to recover from stale locks, but just returns
> a "lock already held" instead?
>
> But even then I think the "mkdir" or "ln −s" solution is
> preferable, because it's simpler and less error prone.

Absolutely!

Regards,
Enrique




Re: how to do file locking using bash?                                              3

								
To top