[Bug 4787] New: Locking can spin if file permissions are wrong

mercurial-bugs at selenic.com mercurial-bugs at selenic.com
Thu Aug 20 00:28:04 UTC 2015


http://bz.selenic.com/show_bug.cgi?id=4787

          Priority: normal
            Bug ID: 4787
                CC: mercurial-devel at selenic.com
          Assignee: bugzilla at selenic.com
           Summary: Locking can spin if file permissions are wrong
          Severity: bug
    Classification: Unclassified
                OS: All
          Reporter: gregory.szorc at gmail.com
          Hardware: All
            Status: UNCONFIRMED
           Version: default branch
         Component: Mercurial
           Product: Mercurial

I was able to coerce an hg 3.4.1 process on Linux to spin a whole CPU core.
strace reveals:

open("/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock",
O_WRONLY|O_CREAT|O_EXCL, 0777) = -1 EEXIST (File exists)
readlink("/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock",
0x7ffc022d9080, 4096) = -1 ENOENT (No such file or directory)
symlink("bdd3fdbbb265:493",
"/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock") = -1 EACCES
(Permission denied)
open("/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock",
O_WRONLY|O_CREAT|O_EXCL, 0777) = -1 EEXIST (File exists)
readlink("/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock",
0x7ffc022d9080, 4096) = -1 ENOENT (No such file or directory)
symlink("bdd3fdbbb265:493",
"/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock") = -1 EACCES
(Permission denied)
open("/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock",
O_WRONLY|O_CREAT|O_EXCL, 0777) = -1 EEXIST (File exists)
readlink("/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock",
0x7ffc022d9080, 4096) = -1 ENOENT (No such file or directory)
symlink("bdd3fdbbb265:493",
"/repo/hg/mozilla/users/user_example.com/repo-1/.hg/wlock") = -1 EACCES
(Permission denied)

gdb shows backtraces like:

(gdb) py-bt
#2 <built-in function open>
#4 file '/usr/lib64/python2.6/site-packages/mercurial/util.py', in 'makelock'
#7 file '/usr/lib64/python2.6/site-packages/mercurial/scmutil.py', in
'makelock'
#10 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in 'trylock'
#13 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in 'lock'
#16 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in '__init__'
#27 file '/usr/lib64/python2.6/site-packages/mercurial/localrepo.py', in
'_lock'
#30 file '/usr/lib64/python2.6/site-packages/mercurial/localrepo.py', in
'wlock'
#34 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'trywritehiddencache'
#37 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'computehidden'
#41 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'filterrevs'
#44 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'computeunserved'
#48 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'filterrevs'
#51 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'changelog'
#59 file '/usr/lib64/python2.6/site-packages/mercurial/bookmarks.py', in
'listbookmarks'
#62 file '/usr/lib64/python2.6/site-packages/mercurial/pushkey.py', in 'list'
#65 file '/usr/lib64/python2.6/site-packages/mercurial/localrepo.py', in
'listkeys'
#68 file '/usr/lib64/python2.6/site-packages/mercurial/wireproto.py', in
'listkeys'
#73 file '/usr/lib64/python2.6/site-packages/mercurial/wireproto.py', in
'dispatch'

and

#2 <built-in function readlink>
#4 file '/usr/lib64/python2.6/site-packages/mercurial/util.py', in 'readlock'
#7 file '/usr/lib64/python2.6/site-packages/mercurial/scmutil.py', in
'readlock'
#10 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in 'testlock'
#13 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in 'trylock'
#16 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in 'lock'
#19 file '/usr/lib64/python2.6/site-packages/mercurial/lock.py', in '__init__'
#30 file '/usr/lib64/python2.6/site-packages/mercurial/localrepo.py', in
'_lock'
#33 file '/usr/lib64/python2.6/site-packages/mercurial/localrepo.py', in
'wlock'
#37 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'trywritehiddencache'
#40 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'computehidden'
#44 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'filterrevs'
#47 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'computeunserved'
#51 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'filterrevs'
#54 file '/usr/lib64/python2.6/site-packages/mercurial/repoview.py', in
'changelog'
#62 file '/usr/lib64/python2.6/site-packages/mercurial/bookmarks.py', in
'listbookmarks'
#65 file '/usr/lib64/python2.6/site-packages/mercurial/pushkey.py', in 'list'
#68 file '/usr/lib64/python2.6/site-packages/mercurial/localrepo.py', in
'listkeys'
#71 file '/usr/lib64/python2.6/site-packages/mercurial/wireproto.py', in
'listkeys'
#76 file '/usr/lib64/python2.6/site-packages/mercurial/wireproto.py', in
'dispatch'

I'm pretty sure we're getting stuck in the following loop:

        while not self.held:
            try:
                self.vfs.makelock(lockname, self.f)
                self.held = 1
            except (OSError, IOError) as why:
                if why.errno == errno.EEXIST:
                    locker = self.testlock()
                    if locker is not None:
                        raise error.LockHeld(errno.EAGAIN,
                                             self.vfs.join(self.f), self.desc,
                                             locker)
                else:
                    raise error.LockUnavailable(why.errno, why.strerror,
                                                why.filename, self.desc)


because "locker" is None and we try immediately again.

I do have multiple clients starting simultaneously that could be racing to
produce this condition.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the Mercurial-devel mailing list