As discussed in Bug 1041, this is indeed an ownership problem. Each C++ object exposed to Python is wrapped with a C++ wrapper object. The wrapper object is stored in a hash table (in C++) that maps the C++ object to a Python reference. The hash table ensures that each time the C++ object is moved from C++ to Python, it shows up to Python as the same reference. The key to the hash table is the address of the object being shoved. When the C++ object is deleted, the hash table entry is deleted.
This particular bug sees a problem when the QItemSelectionModel is shoved across the boundary between C++ and Python. The ownership policy for QItemSelectionModel is incorrect in PySide, so the wrapper object isn't deleted when the C++ object dies, so the hash table entry isn't deleted. If a new object is allocated that just so happens to land at the same memory address as the now dead QItemSelectionModel, Shiboken looks in its hash table and finds the old QItemSelectionModel wrapper object and assumes it has already shoved it across the boundary. So when the new object shows up in Python, Python thinks it's a QItemSelectionModel, which it isn't, object and hilarity ensues. The patch provided on Bug 1041 fixes this problem by setting the appropriate ownership model when a QAbstractItemView returns a QItemSelectionModel object, but has been held up while waiting for the new object management code that is now in PySide 1.1.0. The same bug exists in the development branch of the git repository, so we still need to apply the patch. Nathan On Fri, Jan 6, 2012 at 2:27 PM, S. Champailler <schampail...@skynet.be>wrote: > Dear mailing list, > > I've come across a strange problem leading to very problematic > segmentation faults. Reading here and there I came to the conclusion > that the problem is somehow linked to some ownership issues. > And this proved quite a good idea => no more segmentation faults. > However, in the process of debugging that issue I wrote the > following piece of code, which crashes. My problem is that > I don't understand why it crashes... It'd be nice if someone > could explain in order to make sure my understanding > of the issue is right. > > My best explanation is that the selection model is not > created by PySide but inside Qt. Therefore, somehow, PySide > can't get a hold of it and can't handle its destruction > properly, leaving to leaks... > > I use : > - python 2.7.2 > - PySide-1.0.5qt473-py2.7 > - Windows XP > > Thank you, > > Stefan > > Here comes the code (please note that I have already added it > to bug #1041 at [1]; I've also read [2] but it doesn't seem to > cover this specific issue ) > > > import sys > from PySide.QtGui import * > from PySide.QtCore import * > > class BugWindow(QMainWindow): > def __init__(self): > super(BugWindow,self).__init__() > > # First (not so important) question : who has ownership > # on the table here ? Python or Qt ? Qt doc says > # that QMainWindow takes ownership of the table but since > # we're in a subclass then, who has ownership ? The > # subclass (and thus Python) or the parent class ? > > self.setCentralWidget(QTableView()) > > # We're going to call test_bug() often and until death > # It's just one way of doing this > > self.timer = QTimer(self) > self.timer.timeout.connect(self.test_bug) > > # Adapt this to the performance of your system if needed > # to make sure you exit test_bug() before it is called > # again. > > self.timer.start(20) > > @Slot() > def test_bug(self): > > # First, create a new model ---------------------------------------- > > # If there was a model in self.m before, it is now > # ready for garbage collection => if something > # happens now on the table that requires access > # to the model, we're in for a possible bug > > # parent is None => ownership by Python (and then > # destruction when leaving this method) ? > > self.m = QStandardItemModel(1,1,None) > > > # Set the table's model -------------------------------------------- > > table = self.centralWidget() > > # A new selection model is associated by Qt to the model, cf Qt. doc > # Question is : what happened to the previous selection model ? > > table.setModel(self.m) # model's ownership is left unchanged, cf. > Qt doc. > > # Here, I expect the old model to be definitely > # lost (it is not in self.m anymore and it is > # not referenced by the table anymore). Therefore > # the model can be garbage collected by Python. > > # But for some reason, adding this line makes the > # program crash after a few calls to test_bug() > > table.selectionModel() > > # Interestingly, the following line doesn't crash > # However, it sounds normal. By setting the parent > # to None, I guess the ownership is transferred > # from Qt (which created the selection model) to > # Python (question is : is my guess right ?) > > # table.selectionModel().setParent(None) > > print "go !" > > > app = QApplication(sys.argv) > window = BugWindow() > window.show() > app.exec_() > > > > > > > When the crash occurs, the output looks lilke this : > > > > C:\PORT-STC\pl\ECLIPS~1\PL\src>python bug.py > go ! > go ! > go ! > go ! > go ! > go ! > Object::connect: No such signal > QItemSelectionModel::rowsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::headerDataChanged(Qt::Orientation,int,int) > Object::connect: No such signal > QItemSelectionModel::layoutAboutToBeChanged() > Object::connect: No such signal > QItemSelectionModel::dataChanged(QModelIndex,QModelIndex) > Object::connect: No such signal > QItemSelectionModel::headerDataChanged(Qt::Orientation,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsInserted(QModelIndex,int,int) > Object::connect: No such signal QItemSelectionModel::modelReset() > Object::connect: No such signal QItemSelectionModel::layoutChanged() > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::layoutAboutToBeChanged() > Object::connect: No such signal QItemSelectionModel::layoutChanged() > Object::connect: No such signal > QItemSelectionModel::columnsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::headerDataChanged(Qt::Orientation,int,int) > Object::connect: No such signal > QItemSelectionModel::layoutAboutToBeChanged() > Object::connect: No such signal > QItemSelectionModel::dataChanged(QModelIndex,QModelIndex) > Object::connect: No such signal > QItemSelectionModel::headerDataChanged(Qt::Orientation,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsInserted(QModelIndex,int,int) > Object::connect: No such signal QItemSelectionModel::modelReset() > Object::connect: No such signal QItemSelectionModel::layoutChanged() > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::layoutAboutToBeChanged() > Object::connect: No such signal QItemSelectionModel::layoutChanged() > Object::connect: No such signal > QItemSelectionModel::dataChanged(QModelIndex,QModelIndex) > Object::connect: No such signal > QItemSelectionModel::headerDataChanged(Qt::Orientation,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsInserted(QModelIndex,int,int) > Object::connect: No such signal QItemSelectionModel::modelReset() > Object::connect: No such signal QItemSelectionModel::layoutChanged() > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeRemoved(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::rowsAboutToBeInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::columnsAboutToBeInserted(QModelIndex,int,int) > Object::connect: No such signal > QItemSelectionModel::layoutAboutToBeChanged() > Object::connect: No such signal QItemSelectionModel::layoutChanged() > Error calling slot "test_bug" > Traceback (most recent call last): > File "bug.py", line 71, in test_bug > table.setModel(self.m) # model's ownership is left unchanged, cf. Qt > doc. > AttributeError: 'PySide.QtGui.QItemSelectionModel' object has no attribute > 'rowCount' > Object::disconnect: No such signal > QItemSelectionModel::rowsInserted(QModelIndex,int,int) > > > [1] http://bugs.pyside.org/show_bug.cgi?id=1041 > [2] https://github.com/PySide/PySide/pull/93 > _______________________________________________ > PySide mailing list > PySide@lists.pyside.org > http://lists.pyside.org/listinfo/pyside >
_______________________________________________ PySide mailing list PySide@lists.pyside.org http://lists.pyside.org/listinfo/pyside