diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-02-16 09:56:13 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2010-02-16 09:56:13 (GMT) |
commit | e55a5e173877a20586245eac2080ba9c6fa4de0a (patch) | |
tree | fe3c33342e7eb3e05c44389a0ea8aebf4e1fd296 /src/corelib | |
parent | f3a47f0fe6e9f63c030e6e89f1258d4faf2025cd (diff) | |
download | Qt-e55a5e173877a20586245eac2080ba9c6fa4de0a.zip Qt-e55a5e173877a20586245eac2080ba9c6fa4de0a.tar.gz Qt-e55a5e173877a20586245eac2080ba9c6fa4de0a.tar.bz2 |
Fix a deadlock in kqueue implementation of QFileSystemWatcher
When adding and removing lots of files, the kqueue implementation's
pipe between the worker thread and the main interface would fill up,
causing the thread adding/removing files to block even though the
worker thread was no longer running.
The kqueue interface gives us information about how much data is
available on the pipe (the data member of the kevent struct), so we
should use this to make sure we always empty the pipe. We then iterate
over all the command bytes and make sure we interpret them correctly.
Reviewed-by: Prasanth Ullattil
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_kqueue.cpp | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index f088ded..731406f 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -260,12 +260,22 @@ void QKqueueFileSystemWatcherEngine::run() DEBUG() << "QKqueueFileSystemWatcherEngine: processing kevent" << kev.ident << kev.filter; if (fd == kqpipe[0]) { - char c; - if (read(kqpipe[0], &c, 1) != 1) { + // 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; } - switch (c) { + // 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; @@ -273,7 +283,7 @@ void QKqueueFileSystemWatcherEngine::run() DEBUG() << "QKqueueFileSystemWatcherEngine: thread received '@', continuing..."; break; default: - DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << c; + DEBUG() << "QKqueueFileSystemWatcherEngine: thread received unknow message" << cmd; break; } } else { |