Commits

Robert Brewer committed a9c0e54

Some more info out of gctools

Comments (0)

Files changed (1)

cherrypy/lib/gctools.py

 request_counter.subscribe()
 
 
+def get_context(obj):
+    if isinstance(obj, _cprequest.Request):
+        return "path=%s;stage=%s" % (obj.path_info, obj.stage)
+    elif isinstance(obj, _cprequest.Response):
+        return "status=%s" % obj.status
+    elif isinstance(obj, _cpwsgi.AppResponse):
+        return "PATH_INFO=%s" % obj.environ.get('PATH_INFO', '')
+    elif hasattr(obj, "tb_lineno"):
+        return "tb_lineno=%s" % obj.tb_lineno
+    return ""
+
+
 class GCRoot(object):
     """A CherryPy page handler for testing reference leaks."""
 
         gc.collect()
         unreachable = gc.collect()
         if unreachable:
-            output.append("\n%s unreachable objects:" % unreachable)
+            if objgraph is not None:
+                final = objgraph.by_type('Nondestructible')
+                if final:
+                    objgraph.show_backrefs(final, filename='finalizers.png')
+
             trash = {}
             for x in gc.garbage:
                 trash[type(x)] = trash.get(type(x), 0) + 1
-            trash = [(v, k) for k, v in trash.items()]
-            trash.sort()
-            for pair in trash:
-                output.append("    " + repr(pair))
+            if trash:
+                output.insert(0, "\n%s unreachable objects:" % unreachable)
+                trash = [(v, k) for k, v in trash.items()]
+                trash.sort()
+                for pair in trash:
+                    output.append("    " + repr(pair))
 
         # Check declared classes to verify uncollected instances.
         # These don't have to be part of a cycle; they can be
         # any objects that have unanticipated referrers that keep
         # them from being collected.
+        allobjs = {}
         for cls, minobj, maxobj, msg in self.classes:
-            objs = get_instances(cls)
+            allobjs[cls] = get_instances(cls)
+
+        for cls, minobj, maxobj, msg in self.classes:
+            objs = allobjs[cls]
             lenobj = len(objs)
             if lenobj < minobj or lenobj > maxobj:
                 if minobj == maxobj:
                         "\nExpected %s to %s %r references, got %s." %
                         (minobj, maxobj, cls, lenobj))
 
-                if objgraph is not None:
-                    final = objgraph.by_type('Nondestructible')
-                    if final:
-                        objgraph.show_backrefs(final, filename='finalizers.png')
-
                 for obj in objs:
                     if objgraph is not None:
                         ig = [id(objs), id(inspect.currentframe())]
+                        fname = "graph_%s_%s.png" % (cls.__name__, id(obj))
                         objgraph.show_backrefs(
-                            obj, extra_ignore=ig, max_depth=4,
-                            too_many=20, filename="graph_%s.png" % id(obj))
+                            obj, extra_ignore=ig, max_depth=4, too_many=20,
+                            filename=fname, extra_info=get_context)
                     output.append("\nReferrers for %s (refcount=%s):" %
                                   (repr(obj), sys.getrefcount(obj)))
                     t = ReferrerTree(ignore=[objs], maxdepth=3)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.