Don't overload the meaning of QObjectData::wasDeleted

The union in QObjectPrivate of declarativeData and
currentChildBeingDeleted shouldn't use wasDeleted to determining the
meaning of the unioned pointer. Instead, add
QObjectData::isDeletingChildren, set that in
QObjectPrivate::deleteChildren(), and only use the
currentChildBeingDeleted member when the parent's isDeletingChildren is
set.

This solves aborts seen in autotests when widgets are deleting window
children. The abort comes from QWeakPointer on the parent in the child's
close event handler (the abort checks that wasDeleted is not set).

Change-Id: I1a58449159d4a5312aad8ba12e559d05d6c43d93
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
Bradley T. Hughes 2011-12-09 10:58:14 +01:00 committed by Qt by Nokia
parent fb8dc15ba6
commit a6ae75f92a
2 changed files with 8 additions and 6 deletions

View File

@ -165,6 +165,7 @@ QObjectPrivate::QObjectPrivate(int version)
pendTimer = false; // no timers yet
blockSig = false; // not blocking signals
wasDeleted = false; // double-delete catcher
isDeletingChildren = false; // set by deleteChildren()
sendChildEvents = true; // if we should send ChildInsert and ChildRemove events to parent
receiveChildEvents = true;
postedEvents = 0;
@ -1774,8 +1775,8 @@ void QObject::setParent(QObject *parent)
void QObjectPrivate::deleteChildren()
{
const bool reallyWasDeleted = wasDeleted;
wasDeleted = true;
Q_ASSERT_X(!isDeletingChildren, "QObjectPrivate::deleteChildren()", "isDeletingChildren already set, did this function recurse?");
isDeletingChildren = true;
// delete children objects
// don't use qDeleteAll as the destructor of the child might
// delete siblings
@ -1786,7 +1787,7 @@ void QObjectPrivate::deleteChildren()
}
children.clear();
currentChildBeingDeleted = 0;
wasDeleted = reallyWasDeleted;
isDeletingChildren = false;
}
void QObjectPrivate::setParent_helper(QObject *o)
@ -1796,13 +1797,13 @@ void QObjectPrivate::setParent_helper(QObject *o)
return;
if (parent) {
QObjectPrivate *parentD = parent->d_func();
if (parentD->wasDeleted && wasDeleted
if (parentD->isDeletingChildren && wasDeleted
&& parentD->currentChildBeingDeleted == q) {
// don't do anything since QObjectPrivate::deleteChildren() already
// cleared our entry in parentD->children.
} else {
const int index = parentD->children.indexOf(q);
if (parentD->wasDeleted) {
if (parentD->isDeletingChildren) {
parentD->children[index] = 0;
} else {
parentD->children.removeAt(index);
@ -1829,7 +1830,7 @@ void QObjectPrivate::setParent_helper(QObject *o)
}
}
}
if (!wasDeleted && declarativeData)
if (!isDeletingChildren && declarativeData)
QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
}

View File

@ -99,6 +99,7 @@ public:
uint pendTimer : 1;
uint blockSig : 1;
uint wasDeleted : 1;
uint isDeletingChildren : 1;
uint ownObjectName : 1;
uint sendChildEvents : 1;
uint receiveChildEvents : 1;