tr-summary: keep a weakref to the unfiltered repository

Repoview can have a different life cycle, causing issue in some corner
cases. The particular instance that revealed this comes from localpeer. The
localpeer hold a reference to the unfiltered repository, but calling 'local()'
will create an on-demand 'visible' repoview. That repoview can be garbaged
collected any time. Here is a simplified step by step reproduction::

    1) tr = peer.local().transaction('foo')
    2) tr.close()

After (1), the repoview object is garbage collected, so weakref used in (2)
point to nothing.


Thanks to Sean Farley for helping raising and debugging this issue.
This commit is contained in:
Boris Feld 2017-11-24 21:51:41 -05:00
parent 52b06fe73d
commit cf402c02f7

View File

@ -1233,9 +1233,17 @@ def registersummarycallback(repo, otr, txnname=''):
def reportsummary(func):
"""decorator for report callbacks."""
reporef = weakref.ref(repo)
# The repoview life cycle is shorter than the one of the actual
# underlying repository. So the filtered object can die before the
# weakref is used leading to troubles. We keep a reference to the
# unfiltered object and restore the filtering when retrieving the
# repository through the weakref.
filtername = repo.filtername
reporef = weakref.ref(repo.unfiltered())
def wrapped(tr):
repo = reporef()
if filtername:
repo = repo.filtered(filtername)
func(repo, tr)
newcat = '%2i-txnreport' % len(categories)
otr.addpostclose(newcat, wrapped)