File locking

Alexander Belchenko bialix at ukr.net
Sat Sep 8 16:53:09 BST 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Lukáš Lalinský пишет:
> Hi,
> 
> I'm trying to fix the Windows file locking issues, but after playing
> with it a little I'm starting to think that's the fcntl locking
> implementation the one that is wrong and that there are some serious
> locking issues inside bzrlib. If I understand it correctly, acquiring
> read lock on a file, while write lock is held, should fail, because the
> process would be then allowed to read file in inconsistent state. But if
> I do this on Linux, I get no errors:
> 
>>>> from bzrlib import lock
>>>> a = lock.WriteLock('.bzr/checkout/dirstate')
>>>> b = lock.ReadLock('.bzr/checkout/dirstate')
> 
> If I do the same with the WinAPI implementation, it correctly fails:
> 
>>>> from bzrlib import lock
>>>> a = lock.WriteLock('.bzr/checkout/dirstate')
>>>> b = lock.ReadLock('.bzr/checkout/dirstate')
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
>   File "Z:\home\lukas\projects\bzr\bzr\win32-fixes\bzrlib\lock.py", line
> 303, in __init__
>     self._lock(filename, 'rb', LOCK_SH + LOCK_NB)
>   File "Z:\home\lukas\projects\bzr\bzr\win32-fixes\bzrlib\lock.py", line
> 279, in _lock
>     raise errors.LockContention(filename)
> bzrlib.errors.LockContention: Could not acquire lock
> ".bzr/checkout/dirstate"
> 
> So I started looking more into the fcntl-based file locking on Linux:
> 
>>>> import fcntl
>>>> a = open('.bzr/checkout/dirstate', 'rb+')
>>>> b = open('.bzr/checkout/dirstate', 'rb+')
>>>> fcntl.lockf(a, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>>> fcntl.lockf(b, fcntl.LOCK_SH | fcntl.LOCK_NB) # no IOError
>>>> fcntl.lockf(b, fcntl.LOCK_EX | fcntl.LOCK_NB) # still no IOError!
> 
> But using flock it seems to work correctly:
> 
>>>> import fcntl
>>>> a = open('.bzr/checkout/dirstate', 'rb+')
>>>> b = open('.bzr/checkout/dirstate', 'rb+')
>>>> fcntl.flock(a, fcntl.LOCK_EX | fcntl.LOCK_NB)
>>>> fcntl.flock(b, fcntl.LOCK_SH | fcntl.LOCK_NB)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> IOError: [Errno 11] Resource temporarily unavailable
> 
> Frankly, I don't know much about Linux internals, but after these tests
> does fcntl.lockf look 'no-op' to me. I see that bzrlib.locks handles
> some locking internally by _fcntl_WriteLock._open_locks and
> _fcntl_ReadLock._open_locks, but this of course doesn't cover the case
> of EX+SH locks, multiple running instances of bzr, and will produce very
> strange results if somebody will try to use bzrlib in a threaded (since
> bzrlib is blocking...) GUI application.
> 
> So my question is, does fcntl.lockf actually do something and does this
> code:
> 
>             except IOError, e:
>                 if e.errno in (errno.EAGAIN, errno.EACCES):
>                     # We couldn't grab the lock
>                     self.unlock()
>                 # we should be more precise about whats a locking
>                 # error and whats a random-other error
>                 raise errors.LockContention(e)
> 
> have some test coverage? And finally, am I correct in thinking that a
> try to acquire read lock for a file that is already write-locked should
> fail?

John is the best person to answer this questions, but now he's AFK.
So I try to shed some light.

Linux behavior is wrong (as you say) only within the same process.
When one process hold write lock then the same process can acquire
read lock without any problem. But if one process hold write lock
then another process cannot obtain read lock. You can test this
if in one terminal you run commit with editing log message in external
editor, and try from another terminal run status command.

On Windows write locks always exclusive as you say, even for the same process.

John started to work on exclusive locks for Linux, but not finished this work.
The main problem here is too much tests that will be broken by this change
(around 20 if we look at windows selftest results).

- --
[µ]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFG4sVlzYr338mxwCURAgW0AJ0UgHYYebaivWB9abcicep93uF72gCfcD4A
NHnbOPOTbO7v/MtkoRuwkvw=
=aVao
-----END PGP SIGNATURE-----



More information about the bazaar mailing list