Skip to content

Commit 104f352

Browse files
fix(folderwatcher): ignore stale inotify descriptors
Assisted-by: Codex:GPT-5 Co-authored-by: Claudio Cambra <developer@claudiocambra.com> Signed-off-by: thstyl2000 <18458458+thstyl2000@users.noreply.github.com>
1 parent 2e4fabb commit 104f352

3 files changed

Lines changed: 38 additions & 1 deletion

File tree

src/gui/folderwatcher_linux.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,13 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd)
168168
|| fileName.startsWith(".sync_")) {
169169
continue;
170170
}
171-
const QString p = _watchToPath[event->wd] + '/' + fileName;
171+
const auto watchPathIt = _watchToPath.constFind(event->wd);
172+
if (watchPathIt == _watchToPath.cend()) {
173+
qCDebug(lcFolderWatcher) << "Ignoring event for unknown watch descriptor" << event->wd << fileName;
174+
continue;
175+
}
176+
177+
const QString p = *watchPathIt + '/' + fileName;
172178
_parent->changeDetected(p);
173179

174180
if ((event->mask & (IN_MOVED_TO | IN_CREATE))

src/gui/folderwatcher_linux.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ protected slots:
4141
void slotAddFolderRecursive(const QString &path);
4242

4343
protected:
44+
[[nodiscard]] bool testWatchContains(int watchDescriptor) const { return _watchToPath.contains(watchDescriptor); }
45+
4446
bool findFoldersBelow(const QDir &dir, QStringList &fullList);
4547
void inotifyRegisterPath(const QString &path);
4648
void removeFoldersBelow(const QString &path);

test/testinotifywatcher.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010

1111
#include <QtTest>
1212

13+
#include <array>
14+
#include <climits>
15+
#include <sys/inotify.h>
16+
#include <unistd.h>
17+
1318
#include "folderwatcher_linux.h"
1419
#include "common/utility.h"
1520

@@ -64,6 +69,30 @@ private slots:
6469
QVERIFY2(ok, "findFoldersBelow failed.");
6570
}
6671

72+
void testStaleWatchDescriptorIsIgnored()
73+
{
74+
QVERIFY(!testWatchContains(INT_MAX));
75+
76+
std::array<int, 2> pipeFds {};
77+
QVERIFY(::pipe(pipeFds.data()) == 0);
78+
79+
QByteArray payload(sizeof(inotify_event) + sizeof("lib"), '\0');
80+
const auto event = reinterpret_cast<inotify_event *>(payload.data());
81+
event->wd = INT_MAX;
82+
event->mask = IN_CREATE;
83+
event->cookie = 0;
84+
event->len = sizeof("lib");
85+
memcpy(event->name, "lib", sizeof("lib"));
86+
87+
QCOMPARE(::write(pipeFds[1], payload.constData(), payload.size()), payload.size());
88+
slotReceivedNotification(pipeFds[0]);
89+
90+
::close(pipeFds[0]);
91+
::close(pipeFds[1]);
92+
93+
QVERIFY(!testWatchContains(INT_MAX));
94+
}
95+
6796
void cleanupTestCase() {
6897
if( _root.startsWith(QDir::tempPath() )) {
6998
system( QStringLiteral("rm -rf %1").arg(_root).toLocal8Bit() );

0 commit comments

Comments
 (0)