Don't store iterators on QHash while erasing

QHash::erase() in the new QHash will invalidate
all iterators pointing into the hash.

Change-Id: Ia54e8485a947cd7274f832c7c8c624d0aaded4ba
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Lars Knoll 2020-03-16 13:29:22 +01:00
parent 605bda587e
commit ab91ac0992
3 changed files with 43 additions and 39 deletions

View File

@ -111,37 +111,40 @@ QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &path
void QPollingFileSystemWatcherEngine::timeout() void QPollingFileSystemWatcherEngine::timeout()
{ {
for (auto it = files.begin(), end = files.end(); it != end; /*erasing*/) { for (auto it = files.begin(), end = files.end(); it != end; /*erasing*/) {
auto x = it++; QString path = it.key();
QString path = x.key();
QFileInfo fi(path); QFileInfo fi(path);
if (!fi.exists()) { if (!fi.exists()) {
files.erase(x); it = files.erase(it);
emit fileChanged(path, true); emit fileChanged(path, true);
} else if (x.value() != fi) { continue;
x.value() = fi; } else if (it.value() != fi) {
it.value() = fi;
emit fileChanged(path, false); emit fileChanged(path, false);
} }
++it;
} }
for (auto it = directories.begin(), end = directories.end(); it != end; /*erasing*/) { for (auto it = directories.begin(), end = directories.end(); it != end; /*erasing*/) {
auto x = it++; QString path = it.key();
QString path = x.key();
QFileInfo fi(path); QFileInfo fi(path);
if (!path.endsWith(QLatin1Char('/'))) if (!path.endsWith(QLatin1Char('/')))
fi = QFileInfo(path + QLatin1Char('/')); fi = QFileInfo(path + QLatin1Char('/'));
if (!fi.exists()) { if (!fi.exists()) {
directories.erase(x); it = directories.erase(it);
emit directoryChanged(path, true); emit directoryChanged(path, true);
} else if (x.value() != fi) { continue;
} else if (it.value() != fi) {
fi.refresh(); fi.refresh();
if (!fi.exists()) { if (!fi.exists()) {
directories.erase(x); it = directories.erase(it);
emit directoryChanged(path, true); emit directoryChanged(path, true);
continue;
} else { } else {
x.value() = fi; it.value() = fi;
emit directoryChanged(path, false); emit directoryChanged(path, false);
} }
} }
++it;
} }
} }

View File

@ -697,21 +697,20 @@ void QWindowsFileSystemWatcherEngineThread::run()
qErrnoWarning(error, "%ls", qUtf16Printable(msgFindNextFailed(h))); qErrnoWarning(error, "%ls", qUtf16Printable(msgFindNextFailed(h)));
} }
for (auto it = h.begin(), end = h.end(); it != end; /*erasing*/ ) { for (auto it = h.begin(); it != h.end(); /*erasing*/ ) {
auto x = it++; QString absolutePath = it.value().absolutePath;
QString absolutePath = x.value().absolutePath; QFileInfo fileInfo(it.value().path);
QFileInfo fileInfo(x.value().path); DEBUG() << "checking" << it.key();
DEBUG() << "checking" << x.key();
// i'm not completely sure the fileInfo.exist() check will ever work... see QTBUG-2331 // i'm not completely sure the fileInfo.exist() check will ever work... see QTBUG-2331
// ..however, I'm not completely sure enough to remove it. // ..however, I'm not completely sure enough to remove it.
if (fakeRemove || !fileInfo.exists()) { if (fakeRemove || !fileInfo.exists()) {
DEBUG() << x.key() << "removed!"; DEBUG() << it.key() << "removed!";
if (x.value().isDir) if (it.value().isDir)
emit directoryChanged(x.value().path, true); emit directoryChanged(it.value().path, true);
else else
emit fileChanged(x.value().path, true); emit fileChanged(it.value().path, true);
h.erase(x); it = h.erase(it);
// close the notification handle if the directory has been removed // close the notification handle if the directory has been removed
if (h.isEmpty()) { if (h.isEmpty()) {
@ -726,15 +725,17 @@ void QWindowsFileSystemWatcherEngineThread::run()
// h is now invalid // h is now invalid
break; break;
} }
} else if (x.value().isDir) { continue;
DEBUG() << x.key() << "directory changed!"; } else if (it.value().isDir) {
emit directoryChanged(x.value().path, false); DEBUG() << it.key() << "directory changed!";
x.value() = fileInfo; emit directoryChanged(it.value().path, false);
} else if (x.value() != fileInfo) { it.value() = fileInfo;
DEBUG() << x.key() << "file changed!"; } else if (it.value() != fileInfo) {
emit fileChanged(x.value().path, false); DEBUG() << it.key() << "file changed!";
x.value() = fileInfo; emit fileChanged(it.value().path, false);
it.value() = fileInfo;
} }
++it;
} }
} }
} else { } else {

View File

@ -580,9 +580,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
Qt::TouchPointStates combinedStates; Qt::TouchPointStates combinedStates;
bool hasPressure = false; bool hasPressure = false;
for (auto i = m_contacts.begin(), end = m_contacts.end(); i != end; /*erasing*/) { for (auto it = m_contacts.begin(), end = m_contacts.end(); it != end; /*erasing*/) {
auto it = i++;
Contact &contact(it.value()); Contact &contact(it.value());
if (!contact.state) if (!contact.state)
@ -605,7 +603,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
// Avoid reporting a contact in released state more than once. // Avoid reporting a contact in released state more than once.
if (!m_typeB && contact.state == Qt::TouchPointReleased if (!m_typeB && contact.state == Qt::TouchPointReleased
&& !m_lastContacts.contains(key)) { && !m_lastContacts.contains(key)) {
m_contacts.erase(it); it = m_contacts.erase(it);
continue; continue;
} }
@ -613,6 +611,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
hasPressure = true; hasPressure = true;
addTouchPoint(contact, &combinedStates); addTouchPoint(contact, &combinedStates);
++it;
} }
// Now look for contacts that have disappeared since the last sync. // Now look for contacts that have disappeared since the last sync.
@ -633,22 +632,23 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
} }
// Remove contacts that have just been reported as released. // Remove contacts that have just been reported as released.
for (auto i = m_contacts.begin(), end = m_contacts.end(); i != end; /*erasing*/) { for (auto it = m_contacts.begin(), end = m_contacts.end(); it != end; /*erasing*/) {
auto it = i++;
Contact &contact(it.value()); Contact &contact(it.value());
if (!contact.state) if (!contact.state)
continue; continue;
if (contact.state == Qt::TouchPointReleased) { if (contact.state == Qt::TouchPointReleased) {
if (m_typeB) if (m_typeB) {
contact.state = static_cast<Qt::TouchPointState>(0); contact.state = static_cast<Qt::TouchPointState>(0);
else } else {
m_contacts.erase(it); it = m_contacts.erase(it);
continue;
}
} else { } else {
contact.state = Qt::TouchPointStationary; contact.state = Qt::TouchPointStationary;
} }
++it;
} }
m_lastContacts = m_contacts; m_lastContacts = m_contacts;