config: Avoid generating a reference to myself for Parent.any

The unproxy code for Parent.any can generate a circular reference
in certain situations with classes hierarchies like those in ClockDomain.py.
This patch solves this by marking ouself as visited to make sure the
search does not resolve to a self-reference.
This commit is contained in:
Geoffrey Blake 2014-05-09 18:58:47 -04:00
parent 85940fd537
commit 0c1913336a
2 changed files with 23 additions and 5 deletions

View file

@ -861,7 +861,11 @@ class SimObject(object):
found_obj = None found_obj = None
for child in self._children.itervalues(): for child in self._children.itervalues():
if isinstance(child, ptype): visited = False
if hasattr(child, '_visited'):
visited = getattr(child, '_visited')
if isinstance(child, ptype) and not visited:
if found_obj != None and child != found_obj: if found_obj != None and child != found_obj:
raise AttributeError, \ raise AttributeError, \
'parent.any matched more than one: %s %s' % \ 'parent.any matched more than one: %s %s' % \

View file

@ -82,12 +82,19 @@ class BaseProxy(object):
result, done = self.find(obj) result, done = self.find(obj)
if self._search_up: if self._search_up:
# Search up the tree but mark ourself
# as visited to avoid a self-reference
self._visited = True
obj._visited = True
while not done: while not done:
obj = obj._parent obj = obj._parent
if not obj: if not obj:
break break
result, done = self.find(obj) result, done = self.find(obj)
self._visited = False
base._visited = False
if not done: if not done:
raise AttributeError, \ raise AttributeError, \
"Can't resolve proxy '%s' of type '%s' from '%s'" % \ "Can't resolve proxy '%s' of type '%s' from '%s'" % \
@ -151,10 +158,17 @@ class AttrProxy(BaseProxy):
def find(self, obj): def find(self, obj):
try: try:
val = getattr(obj, self._attr) val = getattr(obj, self._attr)
# for any additional unproxying to be done, pass the visited = False
# current, rather than the original object so that proxy if hasattr(val, '_visited'):
# has the right context visited = getattr(val, '_visited')
obj = val
if not visited:
# for any additional unproxying to be done, pass the
# current, rather than the original object so that proxy
# has the right context
obj = val
else:
return None, False
except: except:
return None, False return None, False
while isproxy(val): while isproxy(val):