Hello Phil,

I've made a unittest for the segfault, it is ran by
executing the command :

python -m nose.core test_qt_bindings.py

It seems to be a matter of keeping too much references,
rather than keeping not enough references.

I know the code in itself is pointless and simply
removing a line in it ensures that it doesn't segfaults,
but I would like to understand why it segfaults.

Thank you and best regards,

Erik

On Thu, 2010-09-09 at 15:46 +0100, Phil Thompson wrote:
> On Thu, 09 Sep 2010 16:35:15 +0200, Erik Janssens
> <erik.janss...@conceptive.be> wrote:
> > Hi,
> > 
> > I understand that it's possible to segfault writing
> > python code (although in my naive view this should
> > not be the case ;)).  I'm rather convinced the code
> > is not doing anything 'illegal', but it would be helpful
> > to have some descriptions on what exactly one can
> > do wrong using pyqt with regard to these kind of
> > segfaults ?
> 
> Typically not keeping a reference to an object. Historically (but I'm not
> sure how much it is still the case, particularly with the new-style
> connections) sip/PyQt would keep pointers to Python objects without taking
> a reference. This was to avoid creating circular references in the days
> before the cyclic garbage collector.
> 
> > I will try to write a test case for this situation,
> > as well as for the deadlocks I mentioned earlier.
> > 
> > Can you maybe comment on the meaning of this line
> > in siplib.c
> > 
> > 7288            assert(PyTuple_Check(mro));
> > 
> > It might help me finding the cause at the python
> > level.
> 
> It's just a sanity check. If Python is working fine then mro will always
> be a tuple, and the following call to PyTuple_GET_SIZE() assumes that it
> is. If it fails then it is likely that mro has been garbage collected and
> the memory reused.
> 
> Phil

"""Test the behaviour of the qt bindings in various circumstances.
"""

import unittest

from PyQt4 import QtGui

class ReferenceHoldingBox(QtGui.QGroupBox):
    """A group box holding references to the table
    view and the table model"""

    def __init__(self, model, table):
        QtGui.QGroupBox.__init__(self)
        self.model = model
        self.table = table
                 
class TableView( QtGui.QWidget  ):
    """A widget containg both a table and a groupbox that
    holds a reference to both the table and the model of the
    table"""

    def __init__( self, table_model ):
        super(TableView, self).__init__()
        widget_layout = QtGui.QVBoxLayout()
        table = QtGui.QTableView( self )
        table.setModel( table_model )
        widget_layout.addWidget( table )
        widget_layout.addWidget( ReferenceHoldingBox( table_model, self ) )
        self.setLayout( widget_layout )

class TableViewCases(unittest.TestCase):
    """Tests related to table views"""

    def setUp(self):
        self.application = QtGui.QApplication([])

    def test_table_view_garbage_collection(self):
        """Create a table view and force its garbage collection"""
        import gc
        for i in range(100):
            print i
            
            class TableModelSubclass(QtGui.QStringListModel):
                pass
    
            widget = TableView( TableModelSubclass() )
            gc.collect()
_______________________________________________
PyQt mailing list    PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt

Reply via email to