summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qfilesystemwatcher_kqueue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qfilesystemwatcher_kqueue.cpp')
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp146
1 files changed, 41 insertions, 105 deletions
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 7379c69d66..2f62176cd4 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -77,39 +77,16 @@ QKqueueFileSystemWatcherEngine *QKqueueFileSystemWatcherEngine::create()
QKqueueFileSystemWatcherEngine::QKqueueFileSystemWatcherEngine(int kqfd)
: kqfd(kqfd)
+ , notifier(kqfd, QSocketNotifier::Read, this)
{
- fcntl(kqfd, F_SETFD, FD_CLOEXEC);
+ connect(&notifier, 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();
-
close(kqfd);
- close(kqpipe[0]);
- close(kqpipe[1]);
foreach (int id, pathToID)
::close(id < 0 ? -id : id);
@@ -192,11 +169,6 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths,
}
}
- if (!isRunning())
- start();
- else
- write(kqpipe[1], "@", 1);
-
return p;
}
@@ -230,102 +202,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, false);
- else
- emit fileChanged(path, false);
- }
+ 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);
}
}
+
}
}