journal: properly check for held lock (issue5349)
authorPierre-Yves David <pierre-yves.david@ens-lyon.org>
Tue, 13 Sep 2016 20:30:19 +0200
changeset 29928 e5a97ec6ebb8
parent 29927 799e36749f1a
child 29929 b3845cab4ddc
journal: properly check for held lock (issue5349) The 'jlock' code meant to check for a held lock, but it actually just checking for a lock object. With CPython, this worked because the 'jlock' object is not referenced outside the '_write' function so reference counting would garbage collect it and the '_lockref' would return None. With pypy, the garbage collection would happen at an undefined time and the '_lockref' can still point to a 'jlock' object outside of '_write'. The right thing to do here is not only to check for a lock object but also to check if the lock is held. We update the code to do so and reuse a utility method that exist on 'localrepo' to help readability. This fix journal related tests with pypy.
hgext/journal.py
--- a/hgext/journal.py	Tue Sep 13 17:46:29 2016 +0200
+++ b/hgext/journal.py	Tue Sep 13 20:30:19 2016 +0200
@@ -267,9 +267,21 @@
         # with a non-local repo (cloning for example).
         cls._currentcommand = fullargs
 
+    def _currentlock(self, lockref):
+        """Returns the lock if it's held, or None if it's not.
+
+        (This is copied from the localrepo class)
+        """
+        if lockref is None:
+            return None
+        l = lockref()
+        if l is None or not l.held:
+            return None
+        return l
+
     def jlock(self, vfs):
         """Create a lock for the journal file"""
-        if self._lockref and self._lockref():
+        if self._currentlock(self._lockref) is not None:
             raise error.Abort(_('journal lock does not support nesting'))
         desc = _('journal of %s') % vfs.base
         try: