[Urwid] Bug: Signal module create backreferences

Ian Ward ian at excess.org
Mon Apr 5 11:44:01 EDT 2010

Dominic LoBue wrote on 2010-04-05 11:11:
> On Sunday, April 4, 2010, Ian Ward <ian at excess.org> wrote:
>> Here's an example of behaviour that I don't want with your current
>> signals_ducktype branch:
>> import urwid
>> b = urwid.Button("test")
>> class Foo(object):
>>     def react(self, b):
>>         print "reacting"
>> f = Foo()
>> urwid.connect_signal(b, 'click', f.react)
>> del f
>> b.keypress((10,), ' ') # this should print "reacting"
>> Instead it causes an error indicating that the callback has been
>> removed.  That's no good: a signal should be enough to keep the function
>> it's referencing alive.
> Personally, I disagree. Besides that causing memory leaks, i think
> deleting an object also means deleting its functions.
> I mean why would you delete an object, or allow all references to an
> object be deleted if you were not done with it yet?

It has the possibility of creating circular reference (which can be
cleaned up automatically by the garbage collector) but not a memory
leak.  This is the same example, but with the intent a little clearer:

import urwid
b = urwid.Button("exit now")
class MySignalHandler(object):
    def exit_pressed(self, b):
        raise urwid.ExitMainLoop

def setup_exit_condition():
    sigh = MySignalHandler()
    urwid.connect_signal(b, 'click', sigh.exit_pressed)

b.keypress((10,), ' ') # this should raise ExitMainLoop

Suppose MySignalHandler had some larger responsibility like a reference
to a logging object that was supposed to use to record the time the user
exited.  Your code will delete the MySignalHandler object even though a
signal is still attached to it.

If your program is having a problem with circular references you can
either break the reference yourself when done with the objects that
contain them, or call gc.collect() more frequently to let python's
garbage collector clean them up for you.


More information about the Urwid mailing list