Patchwork [2,of,2] transaction: clear callback instances after usage

login
register
mail settings
Submitter Gregory Szorc
Date April 16, 2016, 4:08 p.m.
Message ID <a6425e909cd3bdee41ae.1460822920@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/14680/
State Accepted
Headers show

Comments

Gregory Szorc - April 16, 2016, 4:08 p.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@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.
Matt Mackall - April 16, 2016, 9:11 p.m.
On Sat, 2016-04-16 at 09:08 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc@gmail.com>
> # Date 1460822557 25200
> #      Sat Apr 16 09:02:37 2016 -0700
> # Node ID a6425e909cd3bdee41aea6aeed682298c2bc8073
> # Parent  9acb28de651539bfb776eba9e2a59bc8cb3a52f0
> transaction: clear callback instances after usage

These are queued for default, thanks.

-- 
Mathematics is the supreme nostalgia of our time.

Patch

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