Re: [PyQt] Again, problems with garbage collection

2010-03-19 Thread Martin Teichmann
Hi List, Hi Phil,

 I just upgraded to PyQt4 4.7.2 (with Python 2.6.4 on Windows XP)
 and the following little script crashes with unterlying C/C++ object
 has been deleted

 I guess that's a bug.

 Why? It works as I would expect.

Oops. I didn't realize that that's a excpected behaviour. I was under the
impression that Qt shouldn't own objects and delete them, so that
this runtime error was always indicator of a bug (or an indicator that
someone forgot to call the parent's __init__, maybe the error message
should actually read underlying C/C++ object has been deleted or not
yet created, anyhow, that's not the current problem)

Unfortunately, this leads to the somewhat annoying behaviour that
signals are still sent to C++-dead but python-alive objects. That's
especially annoying when the python object ought to be dead already,
just had not been collected yet, as illustrated in the following
example. Note how gc.collect makes a difference, a situation that
better should not happen as garbage collection happens at random intervals...

Greetings

Martin

And here the example:

-- snip -
from PyQt4.QtCore import QObject, SIGNAL, QCoreApplication
import gc

# following two lines not important
from sys import argv
app = QCoreApplication(argv)

class A(QObject):
def __init__(self, p=None):
QObject.__init__(self, p)

def g(self):
self.emit(SIGNAL(sig))

def k(self):
self.emit(SIGNAL(kill))

def f(self):
try:
print self.children() # only to test if C++ object is still alive
except RuntimeError:
print hey, caught runtime error!

def kill(self):
self.setParent(None)

a = A()
b = A(a)
c = A(b)

b.connect(a, SIGNAL(sig), c.f)
b.connect(a, SIGNAL(kill), b.kill)

a.g() # deliver signal to c, all fine
c.v = c # create cycle to prevent immediate collection
b = None
c = None
a.k() # now c ceases existence in the C++ world
print here
a.g() # signal is still delivered
print now collect
gc.collect()
a.g() # signal no more delivered, python object has died
 snip -
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


[PyQt] Again, problems with garbage collection

2010-03-18 Thread Martin Teichmann
Hi List,

I just upgraded to PyQt4 4.7.2 (with Python 2.6.4 on Windows XP)
and the following little script crashes with unterlying C/C++ object
has been deleted

I guess that's a bug.

--- snip --
from PyQt4.QtCore import QObject, SIGNAL, QCoreApplication

# following two lines not important
from sys import argv
app = QCoreApplication(argv)

class A(QObject):
def __init__(self, p=None):
QObject.__init__(self, p)

def g(self):
self.emit(SIGNAL(sig))

def f(self):
print hello

def kill(self):
self.setParent(None)

b = A()
a = A(b)

b.connect(a, SIGNAL(sig), b.f)
a.g()
b.kill()
b = None
a.g()
--- snip -

greetings

Martin
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] Again, problems with garbage collection

2010-03-18 Thread Phil Thompson
On Thu, 18 Mar 2010 15:48:25 +0100, Martin Teichmann
lkb.teichm...@gmail.com wrote:
 Hi List,
 
 I just upgraded to PyQt4 4.7.2 (with Python 2.6.4 on Windows XP)
 and the following little script crashes with unterlying C/C++ object
 has been deleted
 
 I guess that's a bug.

Why? It works as I would expect.

 --- snip --
 from PyQt4.QtCore import QObject, SIGNAL, QCoreApplication
 
 # following two lines not important
 from sys import argv
 app = QCoreApplication(argv)
 
 class A(QObject):
 def __init__(self, p=None):
 QObject.__init__(self, p)
 
 def g(self):
 self.emit(SIGNAL(sig))
 
 def f(self):
 print hello
 
 def kill(self):
 self.setParent(None)
 
 b = A()
 a = A(b)

So a's parent is b.

 b.connect(a, SIGNAL(sig), b.f)
 a.g()
 b.kill()

This has no effect as b doesn't have a parent.

 b = None

This garbage collects the original b. As it didn't have a parent it also
destroys the C++ instance. Because b's C++ instance owns a's it also
destroys a's C++ instance. Because a is still bound to it, the Python
object isn't garbage collected.

 a.g()

self.emit needs a's C++ instance which has been destroyed - so it raises
the exception.

 --- snip -

Phil
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt