Exemplo n.º 1
0
 def __init__(self, evalStr=None, dictKey=NoDictKey):
     # if this is a dictionary lookup, pass dictKey instead of evalStr
     self.evalStr = evalStr
     self.dictKey = NoDictKey
     # is the dictKey a weak reference?
     self._isWeakRef = False
     self._refCount = 0
     if dictKey is not NoDictKey:
         # if we can repr/eval the key, store it as an evalStr
         keyRepr = safeRepr(dictKey)
         useEval = False
         try:
             keyEval = eval(keyRepr)
             useEval = True
         except:
             pass
         if useEval:
             # check to make sure the eval succeeded
             if hash(keyEval) != hash(dictKey):
                 useEval = False
         if useEval:
             # eval/repr succeeded, store as an evalStr
             self.evalStr = '[%s]' % keyRepr
         else:
             try:
                 # store a weakref to the key
                 self.dictKey = weakref.ref(dictKey)
                 self._isWeakRef = True
             except TypeError, e:
                 ContainerLeakDetector.notify.debug('could not weakref dict key %s' % keyRepr)
                 self.dictKey = dictKey
                 self._isWeakRef = False
Exemplo n.º 2
0
 def printReferrers(self, numEach=3):
     """referrers of the first few of each type of object"""
     counts = list(set(self._count2types.keys()))
     counts.sort()
     counts.reverse()
     for count in counts:
         types = makeList(self._count2types[count])
         for typ in types:
             print "\n\nTYPE: %s" % repr(typ)
             for i in xrange(min(numEach, len(self._type2objs[typ]))):
                 obj = self._type2objs[typ][i]
                 print "\nOBJ: %s\n" % safeRepr(obj)
                 referrers = gc.get_referrers(obj)
                 print "%s REFERRERS:\n" % len(referrers)
                 if len(referrers):
                     print getNumberedTypedString(referrers, maxLen=80, numPrefix="REF")
                 else:
                     print "<No Referrers>"
Exemplo n.º 3
0
 def run(self):
     try:
         self._leakDetector._index2containerId2len[self._index] = {}
         ids = self._leakDetector.getContainerIds()
         # record the current len of each container
         for objId in ids:
             yield None
             try:
                 for result in self._leakDetector.getContainerByIdGen(objId):
                     yield None
                 container = result
             except Exception, e:
                 # this container no longer exists
                 if self.notify.getDebug():
                     for contName in self._leakDetector.getContainerNameByIdGen(objId):
                         yield None
                     self.notify.debug(
                         '%s no longer exists; caught exception in getContainerById (%s)' % (
                         contName, e))
                 self._leakDetector.removeContainerById(objId)
                 continue
             if container is None:
                 # this container no longer exists
                 if self.notify.getDebug():
                     for contName in self._leakDetector.getContainerNameByIdGen(objId):
                         yield None
                     self.notify.debug('%s no longer exists; getContainerById returned None' %
                                       contName)
                 self._leakDetector.removeContainerById(objId)
                 continue
             try:
                 cLen = len(container)
             except Exception, e:
                 # this container no longer exists
                 if self.notify.getDebug():
                     for contName in self._leakDetector.getContainerNameByIdGen(objId):
                         yield None
                     self.notify.debug(
                         '%s is no longer a container, it is now %s (%s)' %
                         (contName, safeRepr(container), e))
                 self._leakDetector.removeContainerById(objId)
                 continue
             self._leakDetector._index2containerId2len[self._index][objId] = cLen
Exemplo n.º 4
0
    def getString(self, prevIndirection=None, nextIndirection=None):
        # return our contribution to the full name of an object
        instanceDictStr = '.__dict__'
        if self.evalStr is not None:
            # if we're an instance dict, skip over this one (obj.__dict__[keyName] == obj.keyName)
            if nextIndirection is not None and self.evalStr[-len(instanceDictStr):] == instanceDictStr:
                return self.evalStr[:-len(instanceDictStr)]
            # if the previous indirection was an instance dict, change our syntax from ['key'] to .key
            if prevIndirection is not None and prevIndirection.evalStr is not None:
                if prevIndirection.evalStr[-len(instanceDictStr):] == instanceDictStr:
                    return '.%s' % self.evalStr[2:-2]
            return self.evalStr

        # we're stored as a dict key
        keyRepr = safeRepr(self._getNonWeakDictKey())
        # if the previous indirection was an instance dict, change our syntax from ['key'] to .key
        if prevIndirection is not None and prevIndirection.evalStr is not None:
            if prevIndirection.evalStr[-len(instanceDictStr):] == instanceDictStr:
                return '.%s' % keyRepr
        return '[%s]' % keyRepr
Exemplo n.º 5
0
 def printReferrers(self, numEach=3):
     """referrers of the first few of each type of object"""
     counts = list(set(self._count2types.keys()))
     counts.sort()
     counts.reverse()
     for count in counts:
         types = makeList(self._count2types[count])
         for typ in types:
             print '\n\nTYPE: %s' % repr(typ)
             for i in xrange(min(numEach, len(self._type2objs[typ]))):
                 obj = self._type2objs[typ][i]
                 print '\nOBJ: %s\n' % safeRepr(obj)
                 referrers = gc.get_referrers(obj)
                 print '%s REFERRERS:\n' % len(referrers)
                 if len(referrers):
                     print getNumberedTypedString(referrers,
                                                  maxLen=80,
                                                  numPrefix='REF')
                 else:
                     print '<No Referrers>'
Exemplo n.º 6
0
 def leakContainer(task=None):
     base = getBase()
     if not hasattr(base, 'leakContainer'):
         base.leakContainer = {}
     # use tuples as keys since they can't be weakref'd, and use an instance
     # since it can't be repr/eval'd
     # that will force the leak detector to hold a normal 'non-weak' reference
     class LeakKey:
         pass
     base.leakContainer[(LeakKey(),)] = {}
     # test the non-weakref object reference handling
     if random.random() < .01:
         key = random.choice(base.leakContainer.keys())
         ContainerLeakDetector.notify.debug(
             'removing reference to leakContainer key %s so it will be garbage-collected' % safeRepr(key))
         del base.leakContainer[key]
     taskMgr.doMethodLater(10, leakContainer, 'leakContainer-%s' % serialNum())
     if task:
         return task.done
Exemplo n.º 7
0
    def run(self):
        try:
            # this yields a different set of start refs every time we start a new traversal
            # force creation of a new workingListSelector inside the while loop right off the bat
            workingListSelector = nullGen()
            # this holds the current step of the current traversal
            curObjRef = None
            while True:
                # yield up here instead of at the end, since we skip back to the
                # top of the while loop from various points
                yield None
                #import pdb;pdb.set_trace()
                if curObjRef is None:
                    # choose an object to start a traversal from
                    try:
                        startRefWorkingList = workingListSelector.next()
                    except StopIteration:
                        # do relative # of traversals on each set based on how many refs it contains
                        baseLen = len(self._baseStartRefWorkingList.source)
                        discLen = len(self._discoveredStartRefWorkingList.source)
                        minLen = float(max(1, min(baseLen, discLen)))
                        # this will cut down the traversals of the larger set by 2/3
                        minLen *= 3.
                        workingListSelector = flywheel([self._baseStartRefWorkingList, self._discoveredStartRefWorkingList],
                                                       [baseLen/minLen, discLen/minLen])
                        yield None
                        continue

                    # grab the next start ref from this sequence and see if it's still valid
                    while True:
                        yield None
                        try:
                            curObjRef = startRefWorkingList.refGen.next()
                            break
                        except StopIteration:
                            # we've run out of refs, grab a new set
                            if len(startRefWorkingList.source) == 0:
                                # ref set is empty, choose another
                                break
                            # make a generator that yields containers a # of times that is
                            # proportional to their length
                            for fw in makeFlywheelGen(
                                startRefWorkingList.source.values(),
                                countFunc=lambda x: self.getStartObjAffinity(x),
                                scale=.05):
                                yield None
                            startRefWorkingList.refGen = fw
                    if curObjRef is None:
                        # this ref set is empty, choose another
                        # the base set should never be empty (__builtin__ etc.)
                        continue
                    # do we need to go look up the object in _id2ref? sometimes we do that
                    # to avoid storing multiple redundant refs to a single item
                    if type(curObjRef) in (types.IntType, types.LongType):
                        startId = curObjRef
                        curObjRef = None
                        try:
                            for containerRef in self._leakDetector.getContainerByIdGen(startId):
                                yield None
                        except:
                            # ref is invalid
                            self.notify.debug('invalid startRef, stored as id %s' % startId)
                            self._leakDetector.removeContainerById(startId)
                            continue
                        curObjRef = containerRef

                try:
                    for curObj in curObjRef.getContainerGen():
                        yield None
                except:
                    self.notify.debug('lost current container, ref.getContainerGen() failed')
                    # that container is gone, try again
                    curObjRef = None
                    continue

                self.notify.debug('--> %s' % curObjRef)
                #import pdb;pdb.set_trace()

                # store a copy of the current objRef
                parentObjRef = curObjRef
                # if we hit a dead end, start over from another container
                curObjRef = None

                if hasattr(curObj, '__dict__'):
                    child = curObj.__dict__
                    hasLength = self._hasLength(child)
                    notDeadEnd = not self._isDeadEnd(child)
                    if hasLength or notDeadEnd:
                        # prevent cycles in the references (i.e. base.loader.base)
                        for goesThrough in parentObjRef.goesThroughGen(child):
                            # don't yield, container might lose this element
                            pass
                        if not goesThrough:
                            objRef = ObjectRef(Indirection(evalStr='.__dict__'),
                                               id(child), parentObjRef)
                            yield None
                            if hasLength:
                                for i in self._addContainerGen(child, objRef):
                                    yield None
                            if notDeadEnd:
                                self._addDiscoveredStartRef(child, objRef)
                                curObjRef = objRef
                    continue

                if type(curObj) is types.DictType:
                    key = None
                    attr = None
                    keys = curObj.keys()
                    # we will continue traversing the object graph via one key of the dict,
                    # choose it at random without taking a big chunk of CPU time
                    numKeysLeft = len(keys) + 1
                    for key in keys:
                        yield None
                        numKeysLeft -= 1
                        try:
                            attr = curObj[key]
                        except KeyError, e:
                            # this is OK because we are yielding during the iteration
                            self.notify.debug('could not index into %s with key %s' % (
                                parentObjRef, safeRepr(key)))
                            continue
                        hasLength = self._hasLength(attr)
                        notDeadEnd = False
                        # if we haven't picked the next ref, check if this one is a candidate
                        if curObjRef is None:
                            notDeadEnd = not self._isDeadEnd(attr, key)
                        if hasLength or notDeadEnd:
                            # prevent cycles in the references (i.e. base.loader.base)
                            for goesThrough in parentObjRef.goesThroughGen(curObj[key]):
                                # don't yield, container might lose this element
                                pass
                            if not goesThrough:
                                if curObj is __builtin__.__dict__:
                                    objRef = ObjectRef(Indirection(evalStr='%s' % key),
                                                       id(curObj[key]))
                                else:
                                    objRef = ObjectRef(Indirection(dictKey=key),
                                                       id(curObj[key]), parentObjRef)
                                yield None
                                if hasLength:
                                    for i in self._addContainerGen(attr, objRef):
                                        yield None
                                if notDeadEnd:
                                    self._addDiscoveredStartRef(attr, objRef)
                                    if curObjRef is None and random.randrange(numKeysLeft) == 0:
                                        curObjRef = objRef
                    del key
                    del attr
                    continue

                    try:
                        childNames = dir(curObj)
                    except:
                        pass
                    else:
                        try:
                            index = -1
                            attrs = []
                            while 1:
                                yield None
                                try:
                                    attr = itr.next()
                                except:
                                    # some custom classes don't do well when iterated
                                    attr = None
                                    break
                                attrs.append(attr)
                            # we will continue traversing the object graph via one attr,
                            # choose it at random without taking a big chunk of CPU time
                            numAttrsLeft = len(attrs) + 1
                            for attr in attrs:
                                yield None
                                index += 1
                                numAttrsLeft -= 1
                                hasLength = self._hasLength(attr)
                                notDeadEnd = False
                                if curObjRef is None:
                                    notDeadEnd = not self._isDeadEnd(attr)
                                if hasLength or notDeadEnd:
                                    # prevent cycles in the references (i.e. base.loader.base)
                                    for goesThrough in parentObjRef.goesThrough(curObj[index]):
                                        # don't yield, container might lose this element
                                        pass
                                    if not goesThrough:
                                        objRef = ObjectRef(Indirection(evalStr='[%s]' % index),
                                                           id(curObj[index]), parentObjRef)
                                        yield None
                                        if hasLength:
                                            for i in self._addContainerGen(attr, objRef):
                                                yield None
                                        if notDeadEnd:
                                            self._addDiscoveredStartRef(attr, objRef)
                                            if curObjRef is None and random.randrange(numAttrsLeft) == 0:
                                                curObjRef = objRef
                            del attr
                        except StopIteration, e:
                            pass
                        del itr
                        continue
Exemplo n.º 8
0
    def run(self):
        ContainerReport.PrivateIds.update(set([
            id(ContainerReport.PrivateIds),
            id(self._visitedIds),
            id(self._id2pathStr),
            id(self._id2container),
            id(self._type2id2len),
            id(self._queue),
            id(self._instanceDictIds),
            ]))
        # push on a few things that we want to give priority
        # for the sake of the variable-name printouts
        try:
            base
        except:
            pass
        else:
            self._enqueueContainer( base.__dict__,
                                   'base')
        try:
            simbase
        except:
            pass
        else:
            self._enqueueContainer( simbase.__dict__,
                                   'simbase')
        self._queue.push(__builtins__)
        self._id2pathStr[id(__builtins__)] = ''

        while len(self._queue) > 0:
            # yield up here instead of at the end, since we skip back to the
            # top of the while loop from various points
            yield None
            parentObj = self._queue.pop()
            #print '%s: %s, %s' % (id(parentObj), type(parentObj), self._id2pathStr[id(parentObj)])
            isInstanceDict = False
            if id(parentObj) in self._instanceDictIds:
                isInstanceDict = True

            try:
                if parentObj.__class__.__name__ == 'method-wrapper':
                    continue
            except:
                pass

            if type(parentObj) in (types.StringType, types.UnicodeType):
                continue
            
            if type(parentObj) in (types.ModuleType, types.InstanceType):
                child = parentObj.__dict__
                if self._examine(child):
                    assert (self._queue.back() is child)
                    self._instanceDictIds.add(id(child))
                    self._id2pathStr[id(child)] = str(self._id2pathStr[id(parentObj)])
                continue

            if type(parentObj) is types.DictType:
                key = None
                attr = None
                keys = parentObj.keys()
                try:
                    keys.sort()
                except TypeError, e:
                    self.notify.warning('non-sortable dict keys: %s: %s' % (self._id2pathStr[id(parentObj)], repr(e)))
                for key in keys:
                    try:
                        attr = parentObj[key]
                    except KeyError, e:
                        self.notify.warning('could not index into %s with key %s' % (self._id2pathStr[id(parentObj)],
                                                                                     key))
                    if id(attr) not in self._visitedIds:
                        self._visitedIds.add(id(attr))
                        if self._examine(attr):
                            assert (self._queue.back() is attr)
                            if parentObj is __builtins__:
                                self._id2pathStr[id(attr)] = key
                            else:
                                if isInstanceDict:
                                    self._id2pathStr[id(attr)] = self._id2pathStr[id(parentObj)] + '.%s' % key
                                else:
                                    self._id2pathStr[id(attr)] = self._id2pathStr[id(parentObj)] + '[%s]' % safeRepr(key)
                del key
                del attr
                continue