[Python-bugs-list] [ python-Bugs-505453 ] bug in gc.get_referrers()

noreply@sourceforge.net noreply@sourceforge.net
Fri, 18 Jan 2002 13:18:44 -0800


Bugs item #505453, was opened at 2002-01-18 09:32
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=505453&group_id=5470

Category: Python Interpreter Core
Group: Python 2.2
Status: Open
Resolution: None
Priority: 5
Submitted By: Zooko Ozoko (zooko)
Assigned to: Nobody/Anonymous (nobody)
Summary: bug in gc.get_referrers()

Initial Comment:
`get_referrers()' can return objects which are already
garbage but which are in cycles and haven't been
collected yet.

That in itself is a bug, but there is something
weirder: in my experiments it only returns *some* of
those objects.  Perhaps this is indicative of a deeper
bug in gc.get_referrers()?

Here is a transcript showing how get_referrers()
returns not one referrer (which would be correct), nor
three (which would be the behavior if it included all
the cyclic garbage, but two:

Python 2.2+ (#6, Jan 17 2002, 12:47:08) 
[GCC 3.0.3] on linux2
Type "help", "copyright", "credits" or "license" for
more information.
>>> class A:
...  def __init__(self):
...   self.x = 0
...
>>> a1=A()
>>> a1.x=1
>>> a2=A()
>>> a2.x=2
>>> a1.a=a2
>>> a2.a=a1
>>> a3=A()
>>> a3.x=3
>>> a1.a3=a3
>>> del a1, a2; refs = gc.get_referrers(a3)
>>> len(refs)
2
>>> refs[0]
{'a': <__main__.A instance at 0x8155d54>, 'x': 1, 'a3':
<__main__.A instance at 0x8156d6c>}
>>> refs[1]
{'A': <class __main__.A at 0x815759c>, 'a3':
<__main__.A instance at 0x8156d6c>, 'gc': <module 'gc'
(built-in)>, '__builtins__': <module '__builtin__'
(built-in)>, '__name__': '__main__', 'refs': [{'a':
<__main__.A instance at 0x8155d54>, 'x': 1, 'a3':
<__main__.A instance at 0x8156d6c>}, {...}], '__doc__':
None}


Then in the same session I start again and this time
call `gc.collect()' before calling
`gc.get_referrers()', yielding the expected results:

>>> del a3
>>> collect()
0
>>> a1=A()
>>> a1.x=1
>>> a2=A()
>>> a2.x=2
>>> a1.a=a2
>>> a2.a=a1
>>> a3=A()
>>> a3.x=3
>>> a1.a3=a3
>>> del a1, a2; gc.collect(); refs = gc.get_referrers(a3)
4
>>> len(refs)
1
>>> refs[0]
{'A': <class __main__.A at 0x815759c>, 'a3':
<__main__.A instance at 0x8155bec>, 'gc': <module 'gc'
(built-in)>, '__builtins__': <module '__builtin__'
(built-in)>, '__name__': '__main__', 'refs': [{...}],
'__doc__': None}



If nobody else is more inclined to do it, then please
let me know and I will investigate this bug.

Also note that I am submitting a patch for gcmodule.c
which calls `collect_generations()' at the beginning of
`get_referrers()'.  I do not believe that patch should
be allowed to close this bug, unless someone can
explain the above anomaly.

Regards,

Zooko

---
                 zooko.com
Security and Distributed Systems Engineering
---


----------------------------------------------------------------------

>Comment By: Martin v. Löwis (loewis)
Date: 2002-01-18 13:18

Message:
Logged In: YES 
user_id=21627

I fail to see the bug. You may argue that the object is
conceptually dead already. However:
a) there are different ways to bring it back into life:
   activating DEBUG_SAVEALL may bring them back to life,
   or they may have references originating from an object 
   with an __del__, which are put onto gc.garbage always.
b) tracing all objects is desirable, since it will help
   to explain the reference counter, and may help detecting
   bugs in extension modules.
c) always collecting is expensive.
d) if the application wants to, it can always initiate a
   collection itself.
e) Initiating a collection may call back into Python code,
   thus changing many references in unforeseeable ways;
   this is undesirable if you have managed to bring the
   interpreter into a state where you want to analyse it,
   and then the interpreter messes up everything by invoking
   a collection.

Unless you bring forward arguments why your application
cannot initiate a collection itself before invoking
get_referrers, I'm tempted to close this report.

----------------------------------------------------------------------

Comment By: Zooko Ozoko (zooko)
Date: 2002-01-18 12:50

Message:
Logged In: YES 
user_id=52562


Whoops.  The unexplained behavior is actually perfectly well
explained -- only one of those objects *does* reference a3.

I believe that patch "[ #505464 ] fix (??) bug in
`gc.get_referrers()'" fixes this bug.


----------------------------------------------------------------------

Comment By: Zooko Ozoko (zooko)
Date: 2002-01-18 09:50

Message:
Logged In: YES 
user_id=52562

I submitted a patch: "[ #505464 ] fix (??) bug in
`gc.get_referrers()'" which eliminates the symptoms.

----------------------------------------------------------------------

Comment By: Zooko Ozoko (zooko)
Date: 2002-01-18 09:45

Message:
Logged In: YES 
user_id=52562

By the way, you are welcome to add my account `zooko' to the
techs list and assign the bug to me, in order to indicate
that I should look into it.  :-)

----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=105470&aid=505453&group_id=5470