From 28b8a590c157bc44f2a48f7fd56bc9eff8f6c342 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Wed, 29 May 2019 16:56:08 +0000 Subject: [PATCH] apply upstream QFileSystemWatcher changes that includes the following upstream commits: https://github.com/qt/qtbase/commit/d7ec8bf29ad2f9668c258e9c05012f4a5a0063da https://github.com/qt/qtbase/commit/d6e0306a90597ff17931dba0a11a593c5f1a7221 https://github.com/qt/qtbase/commit/93a466c6fc3c455dcc9bf1292cc6a2725287a94a Signed-off-by: Ivailo Monev --- src/core/io/qfilesystemwatcher.cpp | 48 ++---- src/core/io/qfilesystemwatcher_dnotify.cpp | 4 +- src/core/io/qfilesystemwatcher_inotify.cpp | 24 +-- src/core/io/qfilesystemwatcher_inotify_p.h | 10 +- src/core/io/qfilesystemwatcher_kqueue.cpp | 252 +++++++++++------------------ src/core/io/qfilesystemwatcher_kqueue_p.h | 8 +- src/core/io/qfilesystemwatcher_p.h | 9 +- 7 files changed, 120 insertions(+), 235 deletions(-) diff --git a/src/core/io/qfilesystemwatcher.cpp b/src/core/io/qfilesystemwatcher.cpp index 413d96d65..d5c16b41c 100644 --- a/src/core/io/qfilesystemwatcher.cpp +++ b/src/core/io/qfilesystemwatcher.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -103,43 +102,30 @@ class QPollingFileSystemWatcherEngine : public QFileSystemWatcherEngine } }; - mutable QMutex mutex; QHash files, directories; public: QPollingFileSystemWatcherEngine(); - void run(); - QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); - void stop(); - private Q_SLOTS: void timeout(); + +private: + QTimer timer; }; QPollingFileSystemWatcherEngine::QPollingFileSystemWatcherEngine() + : timer(this) { -#ifndef QT_NO_THREAD - moveToThread(this); -#endif -} - -void QPollingFileSystemWatcherEngine::run() -{ - QTimer timer; - connect(&timer, SIGNAL(timeout()), SLOT(timeout())); - timer.start(PollingInterval); - (void) exec(); } QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) { - QMutexLocker locker(&mutex); QStringList p = paths; QMutableListIterator it(p); while (it.hasNext()) { @@ -160,7 +146,11 @@ QStringList QPollingFileSystemWatcherEngine::addPaths(const QStringList &paths, } it.remove(); } - start(); + if ((!this->files.isEmpty() || + !this->directories.isEmpty()) && + !timer.isActive()) { + timer.start(PollingInterval); + } return p; } @@ -168,7 +158,6 @@ QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &path QStringList *files, QStringList *directories) { - QMutexLocker locker(&mutex); QStringList p = paths; QMutableListIterator it(p); while (it.hasNext()) { @@ -181,22 +170,15 @@ QStringList QPollingFileSystemWatcherEngine::removePaths(const QStringList &path it.remove(); } } - if (this->files.isEmpty() && this->directories.isEmpty()) { - locker.unlock(); - stop(); - wait(); + if (this->files.isEmpty() && + this->directories.isEmpty()) { + timer.stop(); } return p; } -void QPollingFileSystemWatcherEngine::stop() -{ - quit(); -} - void QPollingFileSystemWatcherEngine::timeout() { - QMutexLocker locker(&mutex); QMutableHashIterator fit(files); while (fit.hasNext()) { QHash::iterator x = fit.next(); @@ -421,20 +403,14 @@ QFileSystemWatcher::~QFileSystemWatcher() { Q_D(QFileSystemWatcher); if (d->native) { - d->native->stop(); - d->native->wait(); delete d->native; d->native = 0; } if (d->poller) { - d->poller->stop(); - d->poller->wait(); delete d->poller; d->poller = 0; } if (d->forced) { - d->forced->stop(); - d->forced->wait(); delete d->forced; d->forced = 0; } diff --git a/src/core/io/qfilesystemwatcher_dnotify.cpp b/src/core/io/qfilesystemwatcher_dnotify.cpp index fa29f8077..73e7b6a65 100644 --- a/src/core/io/qfilesystemwatcher_dnotify.cpp +++ b/src/core/io/qfilesystemwatcher_dnotify.cpp @@ -48,11 +48,13 @@ #include #include #include +#include #include #include #include -#include #include + +#include #include #include #include diff --git a/src/core/io/qfilesystemwatcher_inotify.cpp b/src/core/io/qfilesystemwatcher_inotify.cpp index f59294d59..6e52496ca 100644 --- a/src/core/io/qfilesystemwatcher_inotify.cpp +++ b/src/core/io/qfilesystemwatcher_inotify.cpp @@ -77,33 +77,26 @@ QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create() QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd) : inotifyFd(fd) + , notifier(fd, QSocketNotifier::Read, this) { ::fcntl(inotifyFd, F_SETFD, FD_CLOEXEC); - moveToThread(this); + connect(¬ifier, SIGNAL(activated(int)), SLOT(readFromInotify())); } QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine() { + notifier.setEnabled(false); foreach (int id, pathToID) inotify_rm_watch(inotifyFd, id < 0 ? -id : id); ::close(inotifyFd); } -void QInotifyFileSystemWatcherEngine::run() -{ - QSocketNotifier sn(inotifyFd, QSocketNotifier::Read, this); - connect(&sn, SIGNAL(activated(int)), SLOT(readFromInotify())); - (void) exec(); -} - QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) { - QMutexLocker locker(&mutex); - QStringList p = paths; QMutableListIterator it(p); while (it.hasNext()) { @@ -151,8 +144,6 @@ QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, idToPath.insert(id, path); } - start(); - return p; } @@ -160,8 +151,6 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path QStringList *files, QStringList *directories) { - QMutexLocker locker(&mutex); - QStringList p = paths; QMutableListIterator it(p); while (it.hasNext()) { @@ -186,15 +175,8 @@ QStringList QInotifyFileSystemWatcherEngine::removePaths(const QStringList &path return p; } -void QInotifyFileSystemWatcherEngine::stop() -{ - quit(); -} - void QInotifyFileSystemWatcherEngine::readFromInotify() { - QMutexLocker locker(&mutex); - // qDebug() << "QInotifyFileSystemWatcherEngine::readFromInotify"; int buffSize = 0; diff --git a/src/core/io/qfilesystemwatcher_inotify_p.h b/src/core/io/qfilesystemwatcher_inotify_p.h index b974eca8d..1762faeb0 100644 --- a/src/core/io/qfilesystemwatcher_inotify_p.h +++ b/src/core/io/qfilesystemwatcher_inotify_p.h @@ -57,8 +57,8 @@ #ifndef QT_NO_FILESYSTEMWATCHER -#include -#include +#include +#include QT_BEGIN_NAMESPACE @@ -71,22 +71,18 @@ public: static QInotifyFileSystemWatcherEngine *create(); - void run(); - QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); - void stop(); - private Q_SLOTS: void readFromInotify(); private: QInotifyFileSystemWatcherEngine(int fd); int inotifyFd; - QMutex mutex; QHash pathToID; QHash idToPath; + QSocketNotifier notifier; }; diff --git a/src/core/io/qfilesystemwatcher_kqueue.cpp b/src/core/io/qfilesystemwatcher_kqueue.cpp index 4a0987d00..46a3ee7db 100644 --- a/src/core/io/qfilesystemwatcher_kqueue.cpp +++ b/src/core/io/qfilesystemwatcher_kqueue.cpp @@ -76,39 +76,17 @@ QKqueueFileSystemWatcherEngine *QKqueueFileSystemWatcherEngine::create() QKqueueFileSystemWatcherEngine::QKqueueFileSystemWatcherEngine(int kqfd) : kqfd(kqfd) + , notifier(kqfd, QSocketNotifier::Read, this) { - fcntl(kqfd, F_SETFD, FD_CLOEXEC); + connect(¬ifier, SIGNAL(activated(int)), SLOT(readFromKqueue())); - if (pipe(kqpipe) == -1) { - perror("QKqueueFileSystemWatcherEngine: cannot create pipe"); - kqpipe[0] = kqpipe[1] = -1; - return; - } - fcntl(kqpipe[0], F_SETFD, FD_CLOEXEC); - fcntl(kqpipe[1], F_SETFD, FD_CLOEXEC); - - struct kevent kev; - EV_SET(&kev, - kqpipe[0], - EVFILT_READ, - EV_ADD | EV_ENABLE, - 0, - 0, - 0); - if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { - perror("QKqueueFileSystemWatcherEngine: cannot watch pipe, kevent returned"); - return; - } + fcntl(kqfd, F_SETFD, FD_CLOEXEC); } QKqueueFileSystemWatcherEngine::~QKqueueFileSystemWatcherEngine() { - stop(); - wait(); - + notifier.setEnabled(false); close(kqfd); - close(kqpipe[0]); - close(kqpipe[1]); foreach (int id, pathToID) ::close(id < 0 ? -id : id); @@ -119,82 +97,74 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *directories) { QStringList p = paths; - { - QMutexLocker locker(&mutex); - QMutableListIterator it(p); - while (it.hasNext()) { - QString path = it.next(); - int fd; + QMutableListIterator it(p); + while (it.hasNext()) { + QString path = it.next(); + int fd; #if defined(O_EVTONLY) - fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY); + fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY); #else - fd = qt_safe_open(QFile::encodeName(path), O_RDONLY); + fd = qt_safe_open(QFile::encodeName(path), O_RDONLY); #endif - if (fd == -1) { - perror("QKqueueFileSystemWatcherEngine::addPaths: open"); - continue; - } - if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) { - int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE); - if (fddup != -1) { - ::close(fd); - fd = fddup; - } + if (fd == -1) { + perror("QKqueueFileSystemWatcherEngine::addPaths: open"); + continue; + } + if (fd >= (int)FD_SETSIZE / 2 && fd < (int)FD_SETSIZE) { + int fddup = fcntl(fd, F_DUPFD, FD_SETSIZE); + if (fddup != -1) { + ::close(fd); + fd = fddup; } - fcntl(fd, F_SETFD, FD_CLOEXEC); + } + fcntl(fd, F_SETFD, FD_CLOEXEC); - QT_STATBUF st; - if (QT_FSTAT(fd, &st) == -1) { - perror("QKqueueFileSystemWatcherEngine::addPaths: fstat"); + QT_STATBUF st; + if (QT_FSTAT(fd, &st) == -1) { + perror("QKqueueFileSystemWatcherEngine::addPaths: fstat"); + ::close(fd); + continue; + } + int id = (S_ISDIR(st.st_mode)) ? -fd : fd; + if (id < 0) { + if (directories->contains(path)) { ::close(fd); continue; } - int id = (S_ISDIR(st.st_mode)) ? -fd : fd; - if (id < 0) { - if (directories->contains(path)) { - ::close(fd); - continue; - } - } else { - if (files->contains(path)) { - ::close(fd); - continue; - } - } - - struct kevent kev; - EV_SET(&kev, - fd, - EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_CLEAR, - NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, - 0, - 0); - if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { - perror("QKqueueFileSystemWatcherEngine::addPaths: kevent"); + } else { + if (files->contains(path)) { ::close(fd); continue; } + } - it.remove(); - if (id < 0) { - DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path; - directories->append(path); - } else { - DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path; - files->append(path); - } + struct kevent kev; + EV_SET(&kev, + fd, + EVFILT_VNODE, + EV_ADD | EV_ENABLE | EV_CLEAR, + NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, + 0, + 0); + if (kevent(kqfd, &kev, 1, 0, 0, 0) == -1) { + perror("QKqueueFileSystemWatcherEngine::addPaths: kevent"); + ::close(fd); + continue; + } - pathToID.insert(path, id); - idToPath.insert(id, path); + it.remove(); + if (id < 0) { + DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path; + directories->append(path); + } else { + DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path; + files->append(path); } - } - if (!isRunning()) - start(); - else - write(kqpipe[1], "@", 1); + pathToID.insert(path, id); + idToPath.insert(id, path); + } return p; } @@ -229,102 +199,66 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths isEmpty = pathToID.isEmpty(); } - if (isEmpty) { - stop(); - wait(); - } else { - write(kqpipe[1], "@", 1); - } - return p; } -void QKqueueFileSystemWatcherEngine::stop() -{ - write(kqpipe[1], "q", 1); -} - -void QKqueueFileSystemWatcherEngine::run() +void QKqueueFileSystemWatcherEngine::readFromKqueue() { forever { + DEBUG() << "QKqueueFileSystemWatcherEngine: polling for changes"; int r; struct kevent kev; - DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents..."; - EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, 0)); + struct timespec ts = { 0, 0 }; // 0 ts, because we want to poll + EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, &ts)); if (r < 0) { perror("QKqueueFileSystemWatcherEngine: error during kevent wait"); return; + } else if (r == 0) { + // polling returned no events, so stop + break; } else { int fd = kev.ident; DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter; - if (fd == kqpipe[0]) { - // read all pending data from the pipe - QByteArray ba; - ba.resize(kev.data); - if (read(kqpipe[0], ba.data(), ba.size()) != ba.size()) { - perror("QKqueueFileSystemWatcherEngine: error reading from pipe"); - return; - } - // read the command from the buffer (but break and return on 'q') - char cmd = 0; - for (int i = 0; i < ba.size(); ++i) { - cmd = ba.constData()[i]; - if (cmd == 'q') - break; - } - // handle the command - switch (cmd) { - case 'q': - DEBUG() << "QKqueueFileSystemWatcherEngine: thread received 'q', exiting..."; - return; - case '@': - DEBUG() << "QKqueueFileSystemWatcherEngine: thread received '@', continuing..."; - break; - default: - DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << cmd; - break; - } - } else { - QMutexLocker locker(&mutex); - - int id = fd; - QString path = idToPath.value(id); + QMutexLocker locker(&mutex); + + int id = fd; + QString path = idToPath.value(id); + if (path.isEmpty()) { + // perhaps a directory? + id = -id; + path = idToPath.value(id); if (path.isEmpty()) { - // perhaps a directory? - id = -id; - path = idToPath.value(id); - if (path.isEmpty()) { - DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching"; - continue; - } - } - if (kev.filter != EVFILT_VNODE) { - DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter"; + DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching"; continue; } + } + if (kev.filter != EVFILT_VNODE) { + DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter"; + continue; + } - if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) { - DEBUG() << path << "removed, removing watch also"; + if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) { + DEBUG() << path << "removed, removing watch also"; - pathToID.remove(path); - idToPath.remove(id); - ::close(fd); + pathToID.remove(path); + idToPath.remove(id); + ::close(fd); - if (id < 0) - emit directoryChanged(path, true); - else - emit fileChanged(path, true); - } else { - DEBUG() << path << "changed"; + if (id < 0) + emit directoryChanged(path, true); + else + emit fileChanged(path, true); + } else { + DEBUG() << path << "changed"; - if (id < 0) - emit directoryChanged(path, false); - else - emit fileChanged(path, false); - } + if (id < 0) + emit directoryChanged(path, false); + else + emit fileChanged(path, false); } } + } } diff --git a/src/core/io/qfilesystemwatcher_kqueue_p.h b/src/core/io/qfilesystemwatcher_kqueue_p.h index a202666dd..f65532eab 100644 --- a/src/core/io/qfilesystemwatcher_kqueue_p.h +++ b/src/core/io/qfilesystemwatcher_kqueue_p.h @@ -59,6 +59,7 @@ #include #include #include +#include #ifndef QT_NO_FILESYSTEMWATCHER struct kevent; @@ -76,19 +77,18 @@ public: QStringList addPaths(const QStringList &paths, QStringList *files, QStringList *directories); QStringList removePaths(const QStringList &paths, QStringList *files, QStringList *directories); - void stop(); +private Q_SLOTS: + void readFromKqueue(); private: QKqueueFileSystemWatcherEngine(int kqfd); - void run(); - int kqfd; - int kqpipe[2]; QMutex mutex; QHash pathToID; QHash idToPath; + QSocketNotifier notifier; }; QT_END_NAMESPACE diff --git a/src/core/io/qfilesystemwatcher_p.h b/src/core/io/qfilesystemwatcher_p.h index 7851db745..e5cded3f4 100644 --- a/src/core/io/qfilesystemwatcher_p.h +++ b/src/core/io/qfilesystemwatcher_p.h @@ -60,19 +60,16 @@ #include #include -#include QT_BEGIN_NAMESPACE -class QFileSystemWatcherEngine : public QThread +class QFileSystemWatcherEngine : public QObject { Q_OBJECT protected: - inline QFileSystemWatcherEngine(bool move = true) + inline QFileSystemWatcherEngine() { - if (move) - moveToThread(this); } public: @@ -88,8 +85,6 @@ public: QStringList *files, QStringList *directories) = 0; - virtual void stop() = 0; - Q_SIGNALS: void fileChanged(const QString &path, bool removed); void directoryChanged(const QString &path, bool removed); -- 2.11.0