[pygtk] PyGTK object escapes garbage collection
Arjan Molenaar
gaphor at gmail.com
Thu Dec 23 23:28:52 WST 2010
Small question, are the items that are not collected in the destroyed state?
Regards, Arjan
Op 23 dec. 2010 16:02 schreef "Gerald Britton" <gerald.britton at gmail.com>
het volgende:
> We encountered this problem in our project (gramps-project.org). It
> took quite a bit of work to remove the refs to allow GC. Basically, we
> added code to track the callbacks then, when the objects were deleted,
> added code to explicitly remove them (delete them or set them to None)
> to break the cyclical refs. Also, we added code to delete (or set to
> None) attributes that might possibly be involved in the cycle.
>
> It was a lot of work but we eventually stopped the memory leaks.
> Still, I believe that pygtk could be a LOT smarter in this regard. I
> think that what we had to do amounts to fixing a serious design issue
> in pygtk.
>
> On Tue, Dec 21, 2010 at 12:16 PM, Pierre <lists.stackp at online.fr> wrote:
>> Hello list,
>>
>> I run into a surprising behavior regarding garbage collection. In the
>> following example, a Notebook page is removed from its parent widget and
>> destroyed. However, the page is not garbage-collected unless the "tab"
>> widget (a gtk.HBox) is first destroyed.
>>
>> Only the Page instance refers to the "tab" widget. Besides, "tab" is
>> indirectly associated to the page: one of its child widget's signal is
>> connected to a Page method. So we have something like this:
>>
>> page --> tab --> button --> callback --> page --> tab --> etc.
>>
>> Once remove_page() returns, I would expect tab and page to be destroyed
and
>> collected, because both objects become unreachable (unreachable through
>> Python variables and GTK calls). But the gc module shows that they are
not
>> collected.
>>
>> Is this the expected behavior ? I'm using pygtk 2.17.0, gtk 2.20.1, and
>> Python 2.6.6.
>>
>> Thank you for your time.
>>
>> Pierre
>>
>>
>> # ------------------------------------------------------ #
>>
>> import gc
>> import gtk
>> import gobject
>>
>> DESTROY_TAB = False
>>
>> class Page(gtk.VBox):
>>
>> def __init__(self):
>> gtk.VBox.__init__(self)
>> self.pack_start(gtk.TextView(), True, True) # To fill the window
>> button = gtk.Button()
>> button.connect("clicked", self.hello)
>> title = gtk.Label("hello")
>> tab = gtk.HBox()
>> tab.pack_start(title, True, True)
>> tab.pack_end(button, False, False)
>> tab.show_all()
>>
>> # Keeping a reference here is the culprit. Could it be a
>> # circular reference problem ?
>> # tab --> button --> hello --> page --> tab --> ...
>> self.tab = tab
>>
>> def hello(self, widget):
>> print "hello"
>>
>> def add_page(notebook):
>> print "Adding a page to the Notebook."
>> page = Page()
>> page.show_all()
>> notebook.append_page(page, tab_label=page.tab)
>>
>> def remove_page(notebook):
>> print "Removing the page."
>> page = notebook.get_nth_page(0)
>> notebook.remove_page(0)
>> page.destroy()
>> # Destroying page.tab let the GC collect the page.
>> if DESTROY_TAB:
>> page.tab.destroy()
>>
>> def main():
>> notebook = gtk.Notebook()
>> w = gtk.Window()
>> w.add(notebook)
>> w.resize(400, 400)
>> w.show_all()
>> w.connect("destroy", gtk.main_quit)
>> gobject.idle_add(add_page, notebook)
>> gobject.timeout_add(1000, remove_page, notebook)
>> gobject.timeout_add(2000, gtk.main_quit)
>> gtk.main()
>>
>> def seek_page():
>> gc.collect()
>> oo = gc.get_objects()
>> for o in oo:
>> if hasattr(o, "__class__") and (o.__class__ is Page
>> or o.__class__ is gtk.HBox):
>> print
>> print o, "escaped garbage collection"
>> print 'Referrers are :'
>> for r in gc.get_referrers(o):
>> print ' *', repr(r)[:65], '...'
>>
>>
>> main()
>> seek_page()
>>
>>
>> # Output:
>> # ------
>> #
>> # Adding a page to the Notebook.
>> # Removing the page.
>> #
>> # <Page object at 0x98a898c (GtkVBox at 0x9960c18)> escaped garbage
>> collection
>> # Referrers are :
>> # * [(), {'__setattr__': <slot wrapper '__setattr__' of 'object' obje
...
>> # * <bound method Page.hello of <Page object at 0x98a898c (GtkVBox at
...
>> # * <frame object at 0x999f68c> ...
>> #
>> # <gtk.HBox object at 0x98a8a04 (GtkHBox at 0x9960c70)> escaped garbage
>> collection
>> # Referrers are :
>> # * [(), {'__setattr__': <slot wrapper '__setattr__' of 'object' obje
...
>> # * <frame object at 0x999f68c> ...
>> # * {'tab': <gtk.HBox object at 0x98a8a04 (GtkHBox at 0x9960c70)>} ...
>> _______________________________________________
>> pygtk mailing list pygtk at daa.com.au
>> http://www.daa.com.au/mailman/listinfo/pygtk
>> Read the PyGTK FAQ: http://faq.pygtk.org/
>>
>
>
>
> --
> Gerald Britton
> _______________________________________________
> pygtk mailing list pygtk at daa.com.au
> http://www.daa.com.au/mailman/listinfo/pygtk
> Read the PyGTK FAQ: http://faq.pygtk.org/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.daa.com.au/pipermail/pygtk/attachments/20101223/d921b426/attachment.html>
More information about the pygtk
mailing list