summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp15
-rw-r--r--tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp27
2 files changed, 41 insertions, 1 deletions
diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp
index 715e16bc7e..5dc72251ca 100644
--- a/src/corelib/io/qfilesystemwatcher_win.cpp
+++ b/src/corelib/io/qfilesystemwatcher_win.cpp
@@ -361,8 +361,18 @@ void QWindowsFileSystemWatcherEngineThread::run()
if (handles.contains(handle)) {
// qDebug()<<"thread"<<this<<"Acknowledged handle:"<<at<<handle;
QHash<QString, QWindowsFileSystemWatcherEngine::PathInfo> &h = pathInfoForHandle[handle];
+ bool fakeRemove = false;
+
if (!FindNextChangeNotification(handle)) {
const DWORD error = GetLastError();
+
+ if (error == ERROR_ACCESS_DENIED) {
+ // for directories, our object's handle appears to be woken up when the target of a
+ // watch is deleted, before the watched thing is actually deleted...
+ // anyway.. we're given an error code of ERROR_ACCESS_DENIED in that case.
+ fakeRemove = true;
+ }
+
qErrnoWarning(error, "%s", qPrintable(msgFindNextFailed(h)));
}
QMutableHashIterator<QString, QWindowsFileSystemWatcherEngine::PathInfo> it(h);
@@ -371,7 +381,10 @@ void QWindowsFileSystemWatcherEngineThread::run()
QString absolutePath = x.value().absolutePath;
QFileInfo fileInfo(x.value().path);
// qDebug() << "checking" << x.key();
- if (!fileInfo.exists()) {
+
+ // 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.
+ if (fakeRemove || !fileInfo.exists()) {
// qDebug() << x.key() << "removed!";
if (x.value().isDir)
emit directoryChanged(x.value().path, true);
diff --git a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
index 8caccb6da9..78f229a740 100644
--- a/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
+++ b/tests/auto/corelib/io/qfilesystemwatcher/tst_qfilesystemwatcher.cpp
@@ -84,6 +84,9 @@ private slots:
void destroyAfterQCoreApplication();
+ void QTBUG2331();
+ void QTBUG2331_data() { basicTest_data(); }
+
private:
QString m_tempDirPattern;
};
@@ -556,5 +559,29 @@ void tst_QFileSystemWatcher::destroyAfterQCoreApplication()
QTest::qWait(30);
}
+// regression test for QTBUG2331.
+// essentially, on windows, directories were not unwatched after being deleted
+// from the disk, causing all sorts of interesting problems.
+void tst_QFileSystemWatcher::QTBUG2331()
+{
+ QFETCH(QString, backend);
+
+ QTemporaryDir temporaryDirectory(m_tempDirPattern);
+ QVERIFY(temporaryDirectory.isValid());
+ QFileSystemWatcher watcher;
+ watcher.setObjectName(QLatin1String("_qt_autotest_force_engine_") + backend);
+ QVERIFY(watcher.addPath(temporaryDirectory.path()));
+
+ // watch signal
+ QSignalSpy changedSpy(&watcher, SIGNAL(directoryChanged(QString)));
+ QVERIFY(changedSpy.isValid());
+
+ // remove directory, we should get one change signal, and we should no longer
+ // be watching the directory.
+ QVERIFY(temporaryDirectory.remove());
+ QTRY_COMPARE(changedSpy.count(), 1);
+ QCOMPARE(watcher.directories(), QStringList());
+}
+
QTEST_MAIN(tst_QFileSystemWatcher)
#include "tst_qfilesystemwatcher.moc"