From 831e718b0c07fbfb2179eeebe25433575fac4d16 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Thu, 13 Jun 2019 09:59:01 +0200 Subject: [PATCH] FolderWatcher: Become unreliable if test notification fails #7241 Necessary for some filesystems on windows that don't have full file watching capabilities. --- src/gui/folder.cpp | 1 + src/gui/folderwatcher.cpp | 25 +++++++++++++++++++++++++ src/gui/folderwatcher.h | 11 +++++++++++ src/gui/folderwatcher_linux.cpp | 3 ++- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/gui/folder.cpp b/src/gui/folder.cpp index 7952536bb8..0187b51a6a 100644 --- a/src/gui/folder.cpp +++ b/src/gui/folder.cpp @@ -1194,6 +1194,7 @@ void Folder::registerFolderWatcher() connect(_folderWatcher.data(), &FolderWatcher::becameUnreliable, this, &Folder::slotWatcherUnreliable); _folderWatcher->init(path()); + _folderWatcher->startNotificatonTest(path() + QLatin1String(".owncloudsync.log")); } bool Folder::supportsVirtualFiles() const diff --git a/src/gui/folderwatcher.cpp b/src/gui/folderwatcher.cpp index ce248453ae..5050525a02 100644 --- a/src/gui/folderwatcher.cpp +++ b/src/gui/folderwatcher.cpp @@ -33,6 +33,7 @@ #endif #include "folder.h" +#include "filesystem.h" namespace OCC { @@ -75,6 +76,26 @@ bool FolderWatcher::isReliable() const return _isReliable; } +void FolderWatcher::startNotificatonTest(const QString &path) +{ + ASSERT(_testNotificationPath.isEmpty()); + _testNotificationPath = path; + + if (QFile::exists(path)) { + auto mtime = FileSystem::getModTime(path); + FileSystem::setModTime(path, mtime + 1); + } else { + QFile f(path); + f.open(QIODevice::WriteOnly | QIODevice::Append); + } + + QTimer::singleShot(5000, this, [&]() { + if (!_testNotificationPath.isEmpty()) + emit becameUnreliable(tr("The watcher did not receive a test notification.")); + _testNotificationPath.clear(); + }); +} + int FolderWatcher::testLinuxWatchCount() const { #ifdef Q_OS_LINUX @@ -111,6 +132,10 @@ void FolderWatcher::changeDetected(const QStringList &paths) // ------- handle ignores: for (int i = 0; i < paths.size(); ++i) { QString path = paths[i]; + if (!_testNotificationPath.isEmpty() + && Utility::fileNamesEqual(path, _testNotificationPath)) { + _testNotificationPath.clear(); + } if (pathIsIgnored(path)) { continue; } diff --git a/src/gui/folderwatcher.h b/src/gui/folderwatcher.h index 8e28efe65b..3b92d7070f 100644 --- a/src/gui/folderwatcher.h +++ b/src/gui/folderwatcher.h @@ -71,6 +71,14 @@ public: */ bool isReliable() const; + /** + * Triggers a change in the path and verifies a notification arrives. + * + * If no notification is seen, the folderwatcher marks itself as unreliable. + * The path must be ignored by the watcher. + */ + void startNotificatonTest(const QString &path); + /// For testing linux behavior only int testLinuxWatchCount() const; @@ -110,6 +118,9 @@ private: Folder *_folder; bool _isReliable = true; + /** Path of the expected test notification */ + QString _testNotificationPath; + friend class FolderWatcherPrivate; }; } diff --git a/src/gui/folderwatcher_linux.cpp b/src/gui/folderwatcher_linux.cpp index 7943535dbc..ee38a53f62 100644 --- a/src/gui/folderwatcher_linux.cpp +++ b/src/gui/folderwatcher_linux.cpp @@ -171,9 +171,10 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd) if (event->len == 0 || event->wd <= -1) continue; QByteArray fileName(event->name); + // Filter out journal changes - redundant with filtering in + // FolderWatcher::pathIsIgnored. if (fileName.startsWith("._sync_") || fileName.startsWith(".csync_journal.db") - || fileName.startsWith(".owncloudsync.log") || fileName.startsWith(".sync_")) { continue; }