Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make PhysicalFilesWatcher exclusively use polling when pollForChanges=true #41426

Merged
merged 12 commits into from
Nov 12, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ public IChangeToken CreateFileChangeToken(string filter)
}

IChangeToken changeToken = GetOrAddChangeToken(filter);
TryEnableFileSystemWatcher();
if (!PollForChanges)
ericstj marked this conversation as resolved.
Show resolved Hide resolved
{
TryEnableFileSystemWatcher();
}

return changeToken;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.FileProviders.Internal;
using Microsoft.Extensions.FileProviders.Physical;
Expand Down Expand Up @@ -87,6 +89,48 @@ public void GetFileInfoReturnsNotFoundFileInfoForIllegalPathWithLeadingSlashes_U
GetFileInfoReturnsNotFoundFileInfoForIllegalPathWithLeadingSlashes(path);
}

[Fact]
[PlatformSpecific(TestPlatforms.Linux)]
public async void PollingFileProviderShouldntConsumeINotifyInstances()
{
List<IDisposable> disposables = new List<IDisposable>();
using var root = new DisposableFileSystem();

int callbacks = 0;
int maxInstances = int.Parse(File.ReadAllText("/proc/sys/fs/inotify/max_user_instances"));
ericstj marked this conversation as resolved.
Show resolved Hide resolved
int instances = maxInstances + 16;
try
{
for (int i = 0; i < instances; i++)
{
PhysicalFileProvider pfp = new PhysicalFileProvider(root.RootPath)
{
UsePollingFileWatcher = true,
UseActivePolling = true
};
disposables.Add(pfp);
disposables.Add(pfp.Watch("*").RegisterChangeCallback(
o => Interlocked.Increment(ref callbacks),
i));
}

// trigger an event
root.CreateFile("test.txt");

// let some events fire
await Task.Delay(WaitTimeForTokenToFire * 16);
ericstj marked this conversation as resolved.
Show resolved Hide resolved

Assert.NotEqual(0, callbacks);
ericstj marked this conversation as resolved.
Show resolved Hide resolved
}
finally
{
foreach (var disposable in disposables)
{
disposable.Dispose();
}
}
}

private void GetFileInfoReturnsNotFoundFileInfoForIllegalPathWithLeadingSlashes(string path)
{
using (var provider = new PhysicalFileProvider(Path.GetTempPath()))
Expand Down