1. TortoiseHg
  2. TortoiseHg
  3. thg
  4. Issues
Issue #56 resolved

Crash on qref outside thg

Mads Kiilerich
created an issue

Put focus on topmost mq patch, switch to command line and qref, switch back, and crash:

{{{

!python

Please report this bug to http://bitbucket.org/tortoisehg/thg/issues Mercurial version (1.7.2). TortoiseHg version (1.9+147-e14511a3d3fa) Command: CWD: /home/mk/hg/tests Extensions loaded: eol, patchbomb, graphlog, mq, hg-git, hgsubversion, bookmarks, parentrevspec, mbox, convert, extdiff, transplant, rebase Python version: 2.7 (r27:82500, Sep 16 2010, 18:03:06) [GCC 4.5.1 20100907 (Red Hat 4.5.1-3)] Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/repowidget.py", line 629, in repositoryChanged self.rebuildGraph() File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/repowidget.py", line 595, in rebuildGraph self.setupModels() File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/repowidget.py", line 520, in setupModels self.revsetfilter, self) File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/repomodel.py", line 82, in init self.setBranch(branch) File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/repomodel.py", line 117, in setBranch self.ensureBuilt(row=0) File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/repomodel.py", line 163, in ensureBuilt self.graph.build_nodes(nnodes=required, rev=buildrev) File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/graph.py", line 312, in build_nodes for vnext in self.grapher: File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/graph.py", line 110, in revision_grapher p_revs = getparents(ctx) File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/graph.py", line 80, in getparents return [x.rev() for x in ctx.parents() if x] File "/usr/lib/python2.7/site-packages/mercurial/context.py", line 120, in parents return self._parents File "/usr/lib/python2.7/site-packages/mercurial/util.py", line 169, in get result = self.func(obj) File "/usr/lib/python2.7/site-packages/mercurial/context.py", line 667, in _parents self._parents = [changectx(self._repo, x) for x in p] File "/usr/lib/python2.7/site-packages/mercurial/context.py", line 27, in init self._node = self._repo.lookup(changeid) File "/usr/lib/python2.7/site-packages/hgext/parentrevspec.py", line 36, in lookup return _super.lookup(key) File "/usr/lib/python2.7/site-packages/hgext/bookmarks.py", line 267, in lookup return super(bookmark_repo, self).lookup(key) File "/usr/lib/python2.7/site-packages/mercurial/localrepo.py", line 513, in lookup % short(key)) Abort: working directory has unknown parent '1859ddb02358'!

}}}

Comments (8)

  1. Steve Borho

    Dang, I didn't think this was still possible. The stack trace shows that the workbench detected the repository change, invalidated all the repo caches, included dirstate, then refreshed the graph. Somehow repo[None].parents() returned the old working parent hash.

  2. Mads Kiilerich reporter

    Got the same traceback again, but this time another followed immediately after:

    ** Please report this bug to http://bitbucket.org/tortoisehg/thg/issues
    ** Mercurial version (1.7.2).  TortoiseHg version (1.9+189-8ecbb40723db)
    truncated
    Traceback (most recent call last):
      File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/commit.py", line 223, in repositoryChanged
        self.refresh()
      File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/commit.py", line 241, in refresh
        if self.repo.changectx('.').thgmqappliedpatch():
      File "/usr/lib/python2.7/site-packages/tortoisehg/hgqt/thgrepo.py", line 230, in changectx
        changectx = super(thgrepository, self).changectx(changeid)
      File "/usr/lib/python2.7/site-packages/mercurial/localrepo.py", line 544, in changectx
        return self[changeid]
      File "/usr/lib/python2.7/site-packages/mercurial/localrepo.py", line 186, in __getitem__
        return context.changectx(self, changeid)
      File "/usr/lib/python2.7/site-packages/mercurial/context.py", line 28, in __init__
        self._rev = self._repo.changelog.rev(self._node)
      File "/usr/lib/python2.7/site-packages/mercurial/revlog.py", line 532, in rev
        raise LookupError(node, self.indexfile, _('no node'))
    LookupError: 00changelog.i@61fa95ab20d6: no node
    
  3. Steve Borho

    Not unexpected, this time the commit tab was open.

    So was 61fa95ab20d6 the old hash?

    qrefresh does this:

    1. acquire working directory lock
    2. writes new patch file
    3. updates repo.dirstate in memory
    4. strips old qtip
    5. imports new patch file, writing new parents in dirstate
    6. releases wlock
    7. removes undo file

    Our thgrepo poll routine does this:

    1. if locked (wlock or store/lock), exit
    2. check dirstate timestamp
    3. if changed, check locks again. if locked exit, else emit repositoryChanged
    4. check 00changelog.i and patches/series timestaps
    5. if changed, check locks again. if locked exit, else emit repositoryChanged

    I don't see how we're reading an old dirstate file and a new changelog.

    In any event, I'll probably have to catch exceptions like these in a few key places because there is no way to completely eliminate race conditions unless we add the reader locks Matt described. The repository could be modified while the workbench is refreshing.

  4. Steve Borho

    I hammered on "hg qref -D" as fast as I could using up-arrow&return in my shell and was eventually (after 22 tries) able to cause the exceptions in the attached bug report. These are typical of what you get when the qref is started while the workbench is refreshing (integrity and decompression errors).

    I am tempted to experiment with creating our own .hg/store/lock symlink in our poll routine to hold the repository locked while the workbench refreshes.. also a more reliable way to ensure no other lock is held when we emit the repositoryChanged signal from the poll routine.

  5. Mads Kiilerich reporter

    Read locks on refresh/redraw/navigation would be a bit unfortunate.

    Would it be possible to silently catch these exceptions in a few places and retry a couple of times and re-raise the 3rd time it fails? Could a simple hgretry decorator solve the problem for all practical purposes?

  6. Steve Borho

    It would be reasonable to catch RevlogError in the RepositoryChanged signal handler, show an error in the status bar, then ignore the refresh (presumably another refresh is about to happen anyway, since some sort of write operation is in progress).

    To be safe, it should probably clear the graph model as well.

  7. Log in to comment