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