[PATCH 2 of 2] transaction: clear callback instances after usage

Gregory Szorc gregory.szorc at gmail.com
Sat Apr 16 12:08:40 EDT 2016


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1460822557 25200
#      Sat Apr 16 09:02:37 2016 -0700
# Node ID a6425e909cd3bdee41aea6aeed682298c2bc8073
# Parent  9acb28de651539bfb776eba9e2a59bc8cb3a52f0
transaction: clear callback instances after usage

Prevents double usage and helps reduce reference cycles, which
were observed to occur in `hg convert` and other scenarios where
there are multiple transactions per process.

diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -426,16 +426,18 @@ class transaction(object):
     def close(self):
         '''commit the transaction'''
         if self.count == 1:
             self.validator(self)  # will raise exception if needed
             self._generatefiles(group=GenerationGroup.PREFINALIZE)
             categories = sorted(self._finalizecallback)
             for cat in categories:
                 self._finalizecallback[cat](self)
+            # Prevent double usage and help clear cycles.
+            self._finalizecallback = None
             self._generatefiles(group=GenerationGroup.POSTFINALIZE)
 
         self.count -= 1
         if self.count != 0:
             return
         self.file.close()
         self._backupsfile.close()
         # cleanup temporary files
@@ -481,16 +483,18 @@ class transaction(object):
         self.journal = None
 
         self.releasefn(self, True) # notify success of closing transaction
 
         # run post close action
         categories = sorted(self._postclosecallback)
         for cat in categories:
             self._postclosecallback[cat](self)
+        # Prevent double usage and help clear cycles.
+        self._postclosecallback = None
 
     @active
     def abort(self):
         '''abort the transaction (generally called on error, or when the
         transaction is not explicitly committed before going out of
         scope)'''
         self._abort()
 
@@ -534,16 +538,18 @@ class transaction(object):
                     self.opener.unlink(self.journal)
                 return
 
             self.report(_("transaction abort!\n"))
 
             try:
                 for cat in sorted(self._abortcallback):
                     self._abortcallback[cat](self)
+                # Prevent double usage and help clear cycles.
+                self._abortcallback = None
                 _playback(self.journal, self.report, self.opener, self._vfsmap,
                           self.entries, self._backupentries, False)
                 self.report(_("rollback completed\n"))
             except BaseException:
                 self.report(_("rollback failed - please run hg recover\n"))
         finally:
             self.journal = None
             self.releasefn(self, False) # notify failure of transaction


More information about the Mercurial-devel mailing list