Browse Source

more leak debugging

Darren Ranalli 17 years ago
parent
commit
4b0c19f61a
1 changed files with 88 additions and 6 deletions
  1. 88 6
      direct/src/showbase/ContainerLeakDetector.py

+ 88 - 6
direct/src/showbase/ContainerLeakDetector.py

@@ -211,9 +211,10 @@ class ObjectRef:
             return None
             return None
         return container
         return container
 
 
-    def getContainerGen(self):
+    def getContainerGen(self, getInstance=False):
         # try to get a handle on the container by eval'ing and looking things
         # try to get a handle on the container by eval'ing and looking things
         # up in dictionaries, depending on the type of each indirection
         # up in dictionaries, depending on the type of each indirection
+        # if getInstance is True, will return instance instead of instance dict
         #import pdb;pdb.set_trace()
         #import pdb;pdb.set_trace()
         evalStr = ''
         evalStr = ''
         curObj = None
         curObj = None
@@ -237,10 +238,15 @@ class ObjectRef:
             yield None
             yield None
             indirection.release()
             indirection.release()
 
 
+        if getInstance:
+            lenDict = len('.__dict__')
+            if evalStr[-lenDict:] == '.__dict__':
+                evalStr = evalStr[:-lenDict]
+
         # TODO: check that this is still the object we originally pointed to
         # TODO: check that this is still the object we originally pointed to
         yield self._getContainerByEval(evalStr, curObj=curObj)
         yield self._getContainerByEval(evalStr, curObj=curObj)
         
         
-    def getEvalStrGen(self):
+    def getEvalStrGen(self, getInstance=False):
         str = ''
         str = ''
         prevIndirection = None
         prevIndirection = None
         curIndirection = None
         curIndirection = None
@@ -262,6 +268,12 @@ class ObjectRef:
                 nextIndirection = None
                 nextIndirection = None
             str += curIndirection.getString(prevIndirection=prevIndirection,
             str += curIndirection.getString(prevIndirection=prevIndirection,
                                             nextIndirection=nextIndirection)
                                             nextIndirection=nextIndirection)
+
+        if getInstance:
+            lenDict = len('.__dict__')
+            if str[-lenDict:] == '.__dict__':
+                str = str[:-lenDict]
+
         for indirection in indirections:
         for indirection in indirections:
             yield None
             yield None
             indirection.release()
             indirection.release()
@@ -744,6 +756,66 @@ class CheckContainers(Job):
                 raise
                 raise
         yield Job.Done
         yield Job.Done
 
 
+class FPTObjsOfType(Job):
+    def __init__(self, name, leakDetector, otn, doneCallback=None):
+        Job.__init__(self, name)
+        self._leakDetector = leakDetector
+        self.notify = self._leakDetector.notify
+        self._otn = otn
+        self._doneCallback = doneCallback
+        self._ldde = self._leakDetector._getDestroyEvent()
+        self.accept(self._ldde, self._handleLDDestroy)
+        ContainerLeakDetector.addPrivateObj(self.__dict__)
+
+    def destroy(self):
+        self.ignore(self._ldde)
+        self._leakDetector = None
+        self._doneCallback = None
+        ContainerLeakDetector.removePrivateObj(self.__dict__)
+        Job.destroy(self)
+
+    def _handleLDDestroy(self):
+        self.destroy()
+        
+    def getPriority(self):
+        return Job.Priorities.High
+    
+    def run(self):
+        ids = self._leakDetector.getContainerIds()
+        try:
+            for id in ids:
+                getInstance = (self._otn.lower() not in 'dict')
+                yield None
+                try:
+                    for container in self._leakDetector.getContainerByIdGen(
+                        id, getInstance=getInstance):
+                        yield None
+                except:
+                    pass
+                else:
+                    if hasattr(container, '__class__'):
+                        cName = container.__class__.__name__
+                    else:
+                        cName = container.__name__
+                    if (self._otn.lower() in cName.lower()):
+                        try:
+                            for ptc in self._leakDetector.getContainerNameByIdGen(
+                                id, getInstance=getInstance):
+                                yield None
+                        except:
+                            pass
+                        else:
+                            print 'GPTC(' + self._otn + '):' + self.getJobName() + ': ' + ptc
+        except Exception, e:
+            print 'FPTObjsOfType job caught exception: %s' % e
+            if __dev__:
+                raise
+        yield Job.Done
+
+    def finished(self):
+        if self._doneCallback:
+            self._doneCallback(self)
+
 class PruneObjectRefs(Job):
 class PruneObjectRefs(Job):
     """
     """
     Job to destroy any container refs that are no longer valid.
     Job to destroy any container refs that are no longer valid.
@@ -846,6 +918,7 @@ class ContainerLeakDetector(Job):
         jobMgr.add(self)
         jobMgr.add(self)
 
 
     def destroy(self):
     def destroy(self):
+        messenger.send(self._getDestroyEvent())
         self.ignoreAll()
         self.ignoreAll()
         if self._pruneContainersJob is not None:
         if self._pruneContainersJob is not None:
             jobMgr.remove(self._pruneContainersJob)
             jobMgr.remove(self._pruneContainersJob)
@@ -859,6 +932,10 @@ class ContainerLeakDetector(Job):
         del self._index2containerId2len
         del self._index2containerId2len
         del self._index2delay
         del self._index2delay
 
 
+    def _getDestroyEvent(self):
+        # sent when leak detector is about to be destroyed
+        return 'cldDestroy-%s' % self._serialNum
+        
     def getLeakEvent(self):
     def getLeakEvent(self):
         # sent when a leak is detected
         # sent when a leak is detected
         # passes description string as argument
         # passes description string as argument
@@ -879,15 +956,15 @@ class ContainerLeakDetector(Job):
     def getContainerIds(self):
     def getContainerIds(self):
         return self._id2ref.keys()
         return self._id2ref.keys()
 
 
-    def getContainerByIdGen(self, id):
+    def getContainerByIdGen(self, id, **kwArgs):
         # return a generator to look up a container
         # return a generator to look up a container
-        return self._id2ref[id].getContainerGen()
+        return self._id2ref[id].getContainerGen(**kwArgs)
     def getContainerById(self, id):
     def getContainerById(self, id):
         for result in self._id2ref[id].getContainerGen():
         for result in self._id2ref[id].getContainerGen():
             pass
             pass
         return result
         return result
-    def getContainerNameByIdGen(self, id):
-        return self._id2ref[id].getEvalStrGen()
+    def getContainerNameByIdGen(self, id, **kwArgs):
+        return self._id2ref[id].getEvalStrGen(**kwArgs)
     def getContainerNameById(self, id):
     def getContainerNameById(self, id):
         if id in self._id2ref:
         if id in self._id2ref:
             return repr(self._id2ref[id])
             return repr(self._id2ref[id])
@@ -908,6 +985,11 @@ class ContainerLeakDetector(Job):
 
 
         while True:
         while True:
             yield Job.Sleep
             yield Job.Sleep
+
+    def getPathsToContainers(self, name, ot, doneCallback=None):
+        j =  FPTObjsOfType(name, self, ot, doneCallback)
+        jobMgr.add(j)
+        return j
         
         
     def _scheduleNextLeakCheck(self):
     def _scheduleNextLeakCheck(self):
         taskMgr.doMethodLater(self._nextCheckDelay, self._checkForLeaks,
         taskMgr.doMethodLater(self._nextCheckDelay, self._checkForLeaks,