summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp10
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp194
2 files changed, 97 insertions, 107 deletions
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 18c3c9f..1e6dcee 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -228,8 +228,14 @@ void QPollingFileSystemWatcherEngine::timeout()
dit.remove();
emit directoryChanged(path, true);
} else if (x.value() != fi) {
- x.value() = fi;
- emit directoryChanged(path, false);
+ fi.refresh();
+ if (!fi.exists()) {
+ dit.remove();
+ emit directoryChanged(path, true);
+ } else {
+ x.value() = fi;
+ emit directoryChanged(path, false);
+ }
}
}
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 378ad20..3664396 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -117,67 +117,77 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
QStringList *files,
QStringList *directories)
{
- QMutexLocker locker(&mutex);
-
QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- int fd;
+ {
+ QMutexLocker locker(&mutex);
+
+ QMutableListIterator<QString> 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 == -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);
- 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)) {
+ QT_STATBUF st;
+ if (QT_FSTAT(fd, &st) == -1) {
+ perror("QKqueueFileSystemWatcherEngine::addPaths: fstat");
::close(fd);
continue;
}
- } else {
- if (files->contains(path)) {
+ 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");
::close(fd);
continue;
}
- }
- struct kevent kev;
- EV_SET(&kev,
- fd,
- EVFILT_VNODE,
- EV_ADD | EV_ENABLE | EV_ONESHOT,
- 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;
- }
+ it.remove();
+ if (id < 0) {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: added directory path" << path;
+ directories->append(path);
+ } else {
+ DEBUG() << "QKqueueFileSystemWatcherEngine: added file path" << path;
+ files->append(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);
+ pathToID.insert(path, id);
+ idToPath.insert(id, path);
}
-
- pathToID.insert(path, id);
- idToPath.insert(id, path);
}
if (!isRunning())
@@ -192,43 +202,35 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
QStringList *files,
QStringList *directories)
{
- QMutexLocker locker(&mutex);
-
+ bool isEmpty;
QStringList p = paths;
- QMutableListIterator<QString> it(p);
- while (it.hasNext()) {
- QString path = it.next();
- int id = pathToID.take(path);
- QString x = idToPath.take(id);
- if (x.isEmpty() || x != path)
- continue;
-
- int fd = id < 0 ? -id : id;
- struct kevent kev;
- EV_SET(&kev,
- fd,
- EVFILT_VNODE,
- EV_DELETE,
- 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::removeWatch: kevent");
- }
- ::close(fd);
+ {
+ QMutexLocker locker(&mutex);
+ if (pathToID.isEmpty())
+ return p;
+
+ QMutableListIterator<QString> it(p);
+ while (it.hasNext()) {
+ QString path = it.next();
+ int id = pathToID.take(path);
+ QString x = idToPath.take(id);
+ if (x.isEmpty() || x != path)
+ continue;
- it.remove();
- if (id < 0)
- directories->removeAll(path);
- else
- files->removeAll(path);
+ ::close(id < 0 ? -id : id);
+
+ it.remove();
+ if (id < 0)
+ directories->removeAll(path);
+ else
+ files->removeAll(path);
+ }
+ isEmpty = pathToID.isEmpty();
}
- if (pathToID.isEmpty()) {
+ if (isEmpty) {
stop();
- locker.unlock();
wait();
- locker.relock();
} else {
write(kqpipe[1], "@", 1);
}
@@ -243,19 +245,15 @@ void QKqueueFileSystemWatcherEngine::stop()
void QKqueueFileSystemWatcherEngine::run()
{
- static const struct timespec ZeroTimeout = { 0, 0 };
-
forever {
+ int r;
struct kevent kev;
DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents...";
- int r = kevent(kqfd, 0, 0, &kev, 1, 0);
+ EINTR_LOOP(r, kevent(kqfd, 0, 0, &kev, 1, 0));
if (r < 0) {
perror("QKqueueFileSystemWatcherEngine: error during kevent wait");
return;
- }
-
- QMutexLocker locker(&mutex);
- do {
+ } else {
int fd = kev.ident;
DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter;
@@ -287,6 +285,8 @@ void QKqueueFileSystemWatcherEngine::run()
break;
}
} else {
+ QMutexLocker locker(&mutex);
+
int id = fd;
QString path = idToPath.value(id);
if (path.isEmpty()) {
@@ -295,12 +295,12 @@ void QKqueueFileSystemWatcherEngine::run()
path = idToPath.value(id);
if (path.isEmpty()) {
DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent for a file we're not watching";
- goto process_next_event;
+ continue;
}
}
if (kev.filter != EVFILT_VNODE) {
DEBUG() << "QKqueueFileSystemWatcherEngine: received a kevent with the wrong filter";
- goto process_next_event;
+ continue;
}
if ((kev.fflags & (NOTE_DELETE | NOTE_REVOKE | NOTE_RENAME)) != 0) {
@@ -315,31 +315,15 @@ void QKqueueFileSystemWatcherEngine::run()
else
emit fileChanged(path, true);
} else {
- DEBUG() << path << "changed, re-enabling watch";
+ DEBUG() << path << "changed";
if (id < 0)
emit directoryChanged(path, false);
else
emit fileChanged(path, false);
-
- // renable the watch
- EV_SET(&kev,
- fd,
- EVFILT_VNODE,
- EV_ADD | EV_ENABLE | EV_ONESHOT,
- 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::processKqueueEvents: kevent EV_ADD");
- }
}
}
-
- // are there any more?
-process_next_event:
- r = kevent(kqfd, 0, 0, &kev, 1, &ZeroTimeout);
- } while (r > 0);
+ }
}
}