Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 09d712f

Browse files
committed
Merge pull request #2671 from stephentoub/fsw_timeout_poll
Add small timeout to FSW MOVED_FROM polling on Linux
2 parents 1ddfc6d + 919d7af commit 09d712f

File tree

1 file changed

+26
-7
lines changed

1 file changed

+26
-7
lines changed

src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -601,15 +601,34 @@ private void ProcessEvents()
601601
// so we will send a DELETE for this event and a CREATE when the MOVED_TO is eventually processed.
602602
if (_bufferPos == _bufferAvailable)
603603
{
604-
bool success = false;
605-
Interop.libc.PollFlags resultFlags;
606-
_inotifyHandle.DangerousAddRef(ref success);
607-
Debug.Assert(success, "Failed to add-ref inotify handle");
608-
int result = Interop.libc.poll(_inotifyHandle.DangerousGetHandle().ToInt32(), Interop.libc.PollFlags.POLLIN, 0, out resultFlags);
609-
_inotifyHandle.DangerousRelease();
604+
int pollResult;
605+
bool gotRef = false;
606+
try
607+
{
608+
_inotifyHandle.DangerousAddRef(ref gotRef);
609+
610+
// Do the poll with a small timeout value. Community research showed that a few milliseconds
611+
// was enough to allow the vast majority of MOVED_TO events that were going to show
612+
// up to actually arrive. This doesn't need to be perfect; there's always the chance
613+
// that a MOVED_TO could show up after whatever timeout is specified, in which case
614+
// it'll just result in a delete + create instead of a rename. We need the value to be
615+
// small so that we don't significantly delay the delivery of the deleted event in case
616+
// that's actually what's needed (otherwise it'd be fine to block indefinitely waiting
617+
// for the next event to arrive).
618+
const int MillisecondsTimeout = 2;
619+
Interop.libc.PollFlags resultFlags;
620+
pollResult = Interop.libc.poll(_inotifyHandle.DangerousGetHandle().ToInt32(), Interop.libc.PollFlags.POLLIN, MillisecondsTimeout, out resultFlags);
621+
}
622+
finally
623+
{
624+
if (gotRef)
625+
{
626+
_inotifyHandle.DangerousRelease();
627+
}
628+
}
610629

611630
// If we error or don't have any signaled handles, send the deleted event
612-
if (result <= 0)
631+
if (pollResult <= 0)
613632
{
614633
// There isn't any more data in the queue so this is a deleted event
615634
watcher.NotifyFileSystemEventArgs(WatcherChangeTypes.Deleted, expandedName);

0 commit comments

Comments
 (0)