File locking

Lukáš Lalinský lalinsky at gmail.com
Sat Sep 8 11:23:29 BST 2007


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?

Lukas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Toto je =?ISO-8859-1?Q?digit=E1lne?=
	=?ISO-8859-1?Q?_podp=EDsan=E1?= =?UTF-8?Q?_=C4=8Das=C5=A5?=
	=?ISO-8859-1?Q?_spr=E1vy?=
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20070908/a6ae0d22/attachment.pgp 


More information about the bazaar mailing list