changeset 32087:e1938d6051da stable

lock: avoid unintentional lock acquisition at failure of readlock Acquiring lock by vfs.makelock() and getting lock holder (aka "locker") information by vfs.readlock() aren't atomic action. Therefore, failure of the former doesn't ensure success of the latter. Before this patch, lock is unintentionally acquired, if self.parentlock is None (this is default value), and lock._readlock() returns None for ENOENT at vfs.readlock(), because these None are recognized as equal to each other. In this case, lock symlink (or file) isn't created, even though lock is treated as acquired in memory. To avoid this issue, this patch retries lock acquisition immediately, if lock._readlock() returns None "locker". This issue will be covered by a test added in subsequent patch, because simple emulation of ENOENT at vfs.readlock() easily causes another issue. "raising ENOENT only at the first vfs.readlock() invocation" is too complicated for unit test, IMHO.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Mon, 01 May 2017 19:58:52 +0900
parents b59a292d0a53
children 0d892d820a51
files mercurial/lock.py
diffstat 1 files changed, 3 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/lock.py	Mon May 01 05:52:36 2017 +0900
+++ b/mercurial/lock.py	Mon May 01 19:58:52 2017 +0900
@@ -131,6 +131,9 @@
             except (OSError, IOError) as why:
                 if why.errno == errno.EEXIST:
                     locker = self._readlock()
+                    if locker is None:
+                        continue
+
                     # special case where a parent process holds the lock -- this
                     # is different from the pid being different because we do
                     # want the unlock and postrelease functions to be called,