Opened 10 years ago
Closed 10 years ago
#11905 closed defect (fixed)
Recursion depth in git_fs.py traverse - "trac-admin repository sync" fails
Reported by: | anonymous | Owned by: | Jun Omae |
---|---|---|---|
Priority: | normal | Milestone: | 1.0.3 |
Component: | plugin/git | Version: | 1.0.2 |
Severity: | normal | Keywords: | |
Cc: | Branch: | ||
Release Notes: |
Avoid "maximum recursion depth exceeded" error while executing |
||
API Changes: | |||
Internal Changes: |
Description (last modified by )
trac-admin repository sync myrepo fails for me:
File "/usr/lib/python2.7/dist-packages/tracopt/versioncontrol/git/git_fs.py", line 122, in traverse revs[idx:idx] = traverse(parent, seen) File "/usr/lib/python2.7/dist-packages/tracopt/versioncontrol/git/git_fs.py", line 122, in traverse revs[idx:idx] = traverse(parent, seen) File "/usr/lib/python2.7/dist-packages/tracopt/versioncontrol/git/git_fs.py", line 122, in traverse revs[idx:idx] = traverse(parent, seen) File "/usr/lib/python2.7/dist-packages/tracopt/versioncontrol/git/git_fs.py", line 110, in traverse if is_synced(rev): File "/usr/lib/python2.7/dist-packages/tracopt/versioncontrol/git/git_fs.py", line 99, in is_synced """, (self.id, rev)): File "/usr/lib/python2.7/dist-packages/trac/db/api.py", line 122, in execute with self as db: File "/usr/lib/python2.7/dist-packages/trac/db/api.py", line 175, in __enter__ db = self.dbmgr.get_connection(readonly=True) File "/usr/lib/python2.7/dist-packages/trac/db/api.py", line 288, in get_connection db = self._cnx_pool.get_cnx(self.timeout or None) File "/usr/lib/python2.7/dist-packages/trac/db/pool.py", line 213, in get_cnx return _backend.get_cnx(self._connector, self._kwargs, timeout) File "/usr/lib/python2.7/dist-packages/trac/db/pool.py", line 91, in get_cnx self._active[(tid, key)] = (cnx, num) File "/usr/lib/python2.7/threading.py", line 289, in __exit__ return self.__lock.__exit__(*args) File "/usr/lib/python2.7/threading.py", line 216, in __exit__ self.release() File "/usr/lib/python2.7/threading.py", line 210, in release self._note("%s.release(): final release", self) RuntimeError: maximum recursion depth exceeded
If you have a very complicated repository (with lots of merges, e.g. because of migration from other version control systems - probably something like 1000 merges is the limit of trac right now?), the "traverse" method in git_fs.py can fail with a recursion depth exception. The last line of traverse gets invoked when a revision has more than one parent.
May I suggest to use a list based approach that always uses a loop, not falls back to recursion when there is more than one parent?
Some logic (e.g. inserting at revs[idx:idx]) does not appear to be necessary, not even for topology ordering. It only changes the order of the parents backwards, something that can be easily achieved otherwise.
Two modifications in below code (still recursive, though!):
- filter seen parents out early
- collect into a single array of revisions, assuming that the order of parent_revs does not matter anyway.
With below patch, synchronisation seems to work for me - it does not fan out badly, but there are a lot of merges in my codebase. By filtering the seen revisions, the non-recursive codepath seems to be used more often.
-
tracopt/versioncontrol/git/git_fs.py
old new 103 103 def traverse(rev, seen, revs=None): 104 104 if revs is None: 105 105 revs = [] 106 106 while True: 107 107 if rev in seen: 108 108 return revs 109 109 seen.add(rev) 110 110 if is_synced(rev): 111 111 return revs 112 112 revs.append(rev) 113 parent_revs = repos.parent_revs(rev)113 parent_revs = filter(lambda x: not x in seen, repos.parent_revs(rev)) 114 114 if not parent_revs: 115 115 return revs 116 116 if len(parent_revs) == 1: 117 117 rev = parent_revs[0] 118 118 continue 119 idx = len(revs)120 119 traverse(parent_revs.pop(), seen, revs) 121 120 for parent in parent_revs: 122 revs[idx:idx] = traverse(parent, seen)121 traverse(parent, seen, revs)
Attachments (0)
Change History (5)
comment:1 by , 10 years ago
Component: | version control → plugin/git |
---|---|
Description: | modified (diff) |
Milestone: | → 1.0.3 |
Owner: | set to |
Status: | new → assigned |
Version: | → 1.0.2 |
comment:2 by , 10 years ago
I confirmed suggested fix for git repository with 2000 merge commits. The issue still exists. I just created patch in [55f4f3dd/jomae.git] (jomae.git@t11905).
Could you please try the patch on your environment?
comment:3 by , 10 years ago
Added unit tests for this issue in [61b3244ff/jomae.git]. I'll push proposed changes tonight.
comment:4 by , 10 years ago
I'm running late in creating the release but plan to do that tomorrow, so pushing proposed changes tonight would be good timing.
comment:5 by , 10 years ago
Release Notes: | modified (diff) |
---|---|
Resolution: | → fixed |
Status: | assigned → closed |
Thanks for the reporting! I'll reproduce it and confirm suggested fix.