finding memory leak in edgewall trac 0.11
rupert.thurner
rupert.thurner at gmail.com
Sun Jan 20 06:40:39 EST 2008
On Jan 19, 10:31 pm, Christian Heimes <li... at cheimes.de> wrote:
> Jeroen Ruigrok van der Werven wrote:
>
> > Hi Christian,
>
> > -On [20080119 16:16], Christian Heimes (li... at cheimes.de) wrote:
> >> I forgot one important point in my reply. The GC module contains some
> >> useful methods for debugging. Check gc.garbage. It should be empty.
>
> > Yeah, we're messing around with that stuff as well as many other ways of
> > trying to track issues, but it can really be looking for a needle in a
> > haystack to be honest.
> > There's so much output that, I guess, make sense only when you're semi-deep
> > into the Python internals to even make heads or tails out of it. =\
> > And even third-party code is not helping much to reduce the clutter and
> > provide insight.
>
> Under normal circumstances gc.garbage should be an empty list. In
> general it's a bad sign if gc.garbage contains lots of objects.
>
> I found several potential leaks in trac:
>
> $ find -name \*.py | xargs grep __del__
> ./trac/versioncontrol/svn_fs.py: def __del__(self):
> ./trac/versioncontrol/svn_fs.py: def __del__(self):
> ./trac/db/pool.py: def __del__(self):
>
> $ find -name \*.py | xargs grep frame
> ./trac/web/main.py:
> [...]
> ./trac/core.py: frame = sys._getframe(1)
> ./trac/core.py: locals_ = frame.f_locals
>
> I recommend that you either replace __del__ with a weak reference
> callback or to remove it. Referencing a frame, traceback or f_locals is
> going to leak, too. You *must* explicitly del every frame and locals
> variable.
>
> Christian
many thanks! as the main change was replacing clearsilver with genshi,
this means one could do the same thing with genshi, http://genshi.edgewall.org/?
$ find -name \*.py | xargs grep frame
./genshi/filters/html.py: 'dir', 'disabled', 'enctype', 'for',
'frame', 'headers', 'height',
./genshi/input.py: _EMPTY_ELEMS = frozenset(['area', 'base',
'basefont', 'br', 'col', 'frame',
./genshi/output.py: 'http://www.w3.org/TR/html4/frameset.dtd'
./genshi/output.py: 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-
frameset.dtd'
./genshi/output.py: * "html-transitional" for the HTML 4.01
frameset DTD
./genshi/output.py: * "xhtml-frameset" for the XHTML 1.0
frameset DTD
./genshi/output.py: 'html-frameset': DocType.HTML_FRAMESET,
./genshi/output.py: 'xhtml-frameset': cls.XHTML_FRAMESET,
./genshi/output.py: _EMPTY_ELEMS = frozenset(['area', 'base',
'basefont', 'br', 'col', 'frame',
./genshi/template/base.py: _ctxt2dict = lambda ctxt: ctxt.frames[0]
./genshi/template/base.py: self.frames = deque([data])
./genshi/template/base.py: self.pop = self.frames.popleft
./genshi/template/base.py: self.push = self.frames.appendleft
./genshi/template/base.py: return repr(list(self.frames))
./genshi/template/base.py: for frame in self.frames:
./genshi/template/base.py: if key in frame:
./genshi/template/base.py: del frame[key]
./genshi/template/base.py: value, frame = self._find(key)
./genshi/template/base.py: if frame is None:
./genshi/template/base.py: self.frames[0][key] = value
./genshi/template/base.py: """Retrieve a given variable's value
and the frame it was found in.
./genshi/template/base.py: for frame in self.frames:
./genshi/template/base.py: if key in frame:
./genshi/template/base.py: return frame[key], frame
./genshi/template/base.py: for frame in self.frames:
./genshi/template/base.py: if key in frame:
./genshi/template/base.py: return frame[key]
./genshi/template/base.py: for frame in self.frames:
./genshi/template/base.py: keys += [key for key in frame if
key not in keys]
./genshi/template/directives.py: # Store the function reference
in the bottom context frame so that it
./genshi/template/directives.py: ctxt.frames[-1][self.name] =
function
./genshi/template/directives.py: frame = {}
./genshi/template/directives.py: ctxt.push(frame)
./genshi/template/tests/directives.py: frame =
exc_traceback.tb_next
./genshi/template/tests/directives.py: frames = []
./genshi/template/tests/directives.py: while frame.tb_next:
./genshi/template/tests/directives.py: frame =
frame.tb_next
./genshi/template/tests/directives.py:
frames.append(frame)
./genshi/template/tests/directives.py:
frames[-1].tb_frame.f_code.co_name)
./genshi/template/tests/directives.py:
frames[-1].tb_frame.f_code.co_filename)
./genshi/template/tests/directives.py: self.assertEqual(2,
frames[-1].tb_lineno)
./genshi/template/tests/eval.py: frame =
exc_traceback.tb_next
./genshi/template/tests/eval.py: frames = []
./genshi/template/tests/eval.py: while frame.tb_next:
./genshi/template/tests/eval.py: frame = frame.tb_next
./genshi/template/tests/eval.py: frames.append(frame)
./genshi/template/tests/eval.py:
frames[-3].tb_frame.f_code.co_name)
./genshi/template/tests/eval.py:
frames[-3].tb_frame.f_code.co_filename)
./genshi/template/tests/eval.py: self.assertEqual(50,
frames[-3].tb_lineno)
./genshi/template/tests/eval.py: frame =
exc_traceback.tb_next
./genshi/template/tests/eval.py: while frame.tb_next:
./genshi/template/tests/eval.py: frame = frame.tb_next
./genshi/template/tests/eval.py: code =
frame.tb_frame.f_code
./genshi/template/tests/eval.py: self.fail("never found
the frame I was looking for")
./genshi/template/tests/eval.py: self.assertEqual(50,
frame.tb_lineno)
./genshi/template/tests/eval.py: frame =
exc_traceback.tb_next
./genshi/template/tests/eval.py: while frame.tb_next:
./genshi/template/tests/eval.py: frame = frame.tb_next
./genshi/template/tests/eval.py: code =
frame.tb_frame.f_code
./genshi/template/tests/eval.py: self.fail("never found
the frame I was looking for")
./genshi/template/tests/eval.py: self.assertEqual(50,
frame.tb_lineno)
rupert
More information about the Python-list
mailing list