QComboBox: close the container explicitly before destroying it
QComboBox destroys the container of the view in its own destructor, before the QWidget destructor is entered. The container is a toplevel widget, so destroying that will destroy a platform window, triggering an accessibility update cycle that calls back into Qt. As the QComboBox has not yet reached the QWidget destructor, it still considers itself as visible and focused. The accessibility query will therefore operate on it, as the focused object. Probing the state accesses the view. The view however is already partially destroyed, as the container's destruction has already passed the QWidget destructor deleting all its children. As a result, we are returning a pointer to a QAbstractItemView that's already in the QWidget destructor, resulting in a crash. Options for fixing this would be resetting the view pointer in ~QComboBoxPrivateContainer to nullptr and to test for that in client code. Doing that triggered crashes in tests, as QComboBox::view() so far has never returned a nullptr no matter the state of the combobox. So instead, close the container explicitly before destroying it. This way, any update cycle resulting in reentrancy (such as accessibility of backingstore flushing when the container closes) will be completed before objects are destroyed. This amends fde358dd9069d0695f113ec6ba98efebedd1e520, which added the explicit destruction of the container, for similar reasons. This seems to be a combobox-specific problem due to the combination of explicit destruction of (toplevel) child widgets, resulting event processing, and exposing of internal widget states through public API as part of the widget's accessible state. Pick-to: 6.8 6.5 Fixes: QTBUG-132310 Change-Id: I74df5b71906ce8153b12ddc35b897a44e7752907 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> (cherry picked from commit 74e5a51babe0a133ce0fe9b907ef77cc606fbcb9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
d3e03d1da0
commit
4874a7b13c
@ -441,7 +441,7 @@ QAccessible::State QAccessibleComboBox::state() const
|
||||
|
||||
if (QComboBox *cBox = comboBox()) {
|
||||
s.expandable = true;
|
||||
s.expanded = isValid() && cBox->view()->isVisible();
|
||||
s.expanded = isValid() && cBox->view() && cBox->view()->isVisible();
|
||||
s.editable = cBox->isEditable();
|
||||
}
|
||||
return s;
|
||||
|
@ -1472,8 +1472,14 @@ QComboBox::~QComboBox()
|
||||
; // objects can't throw in destructor
|
||||
}
|
||||
|
||||
// Dispose of container before QComboBox goes away
|
||||
delete d->container;
|
||||
// Dispose of container before QComboBox goes away. Close explicitly so that
|
||||
// update cycles back into the combobox (e.g. from accessibility when the
|
||||
// active window changes) are completed first.
|
||||
if (d->container) {
|
||||
d->container->close();
|
||||
delete d->container;
|
||||
d->container = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
Loading…
x
Reference in New Issue
Block a user