diff --git src/corelib/io/qfilesystemwatcher_kqueue.cpp src/corelib/io/qfilesystemwatcher_kqueue.cpp index 99c165e..ce79cf7 100644 --- src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -133,6 +133,14 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, perror("QKqueueFileSystemWatcherEngine::addPaths: open"); continue; } + if (fd >= FD_SETSIZE / 2 && fd < 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) { @@ -157,7 +165,7 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, EV_SET(&kev, fd, EVFILT_VNODE, - EV_ADD | EV_ENABLE | EV_ONESHOT, + EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0); @@ -180,6 +188,8 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, idToPath.insert(id, path); } + locker.unlock(); + if (!isRunning()) start(); else @@ -203,19 +213,7 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths 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); + ::close(id < 0 ? -id : id); it.remove(); if (id < 0) @@ -225,11 +223,11 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths } if (pathToID.isEmpty()) { + locker.unlock(); stop(); - locker.unlock(); wait(); - locker.relock(); } else { + locker.unlock(); write(kqpipe[1], "@", 1); } @@ -243,19 +241,18 @@ void QKqueueFileSystemWatcherEngine::stop() void QKqueueFileSystemWatcherEngine::run() { - static const struct timespec ZeroTimeout = { 0, 0 }; - forever { struct kevent kev; DEBUG() << "QKqueueFileSystemWatcherEngine: waiting for kevents..."; int r = kevent(kqfd, 0, 0, &kev, 1, 0); if (r < 0) { + if(errno == EINTR) { + DEBUG() << "QKqueueFileSystemWatcherEngine: kevent call was interrupted, restarting..."; + continue; + } 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 +284,8 @@ void QKqueueFileSystemWatcherEngine::run() break; } } else { + QMutexLocker locker(&mutex); + int id = fd; QString path = idToPath.value(id); if (path.isEmpty()) { @@ -315,30 +314,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? - r = kevent(kqfd, 0, 0, &kev, 1, &ZeroTimeout); - } while (r > 0); + } } }