Given the program:
using System;
using System.IO;
namespace fsw_bug_poc
{
class Program
{
private static FileSystemWatcher _fileSystemWatcher;
static void Main(string[] args)
{
_fileSystemWatcher = new FileSystemWatcher("Watched", "*.*");
_fileSystemWatcher.Changed += Notify;
_fileSystemWatcher.Created += Notify;
_fileSystemWatcher.Deleted += Notify;
_fileSystemWatcher.Renamed += Notify;
_fileSystemWatcher.IncludeSubdirectories = true;
_fileSystemWatcher.EnableRaisingEvents = true;
Console.ReadKey(false);
}
private static void Notify(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"{e.FullPath} {e.ChangeType}");
}
}
}
The Dockerfile:
FROM mcr.microsoft.com/dotnet/core/runtime:2.2-stretch-slim AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
WORKDIR /src
COPY ["fsw-bug-poc.csproj", ""]
RUN dotnet restore "fsw-bug-poc.csproj"
COPY . .
WORKDIR "/src/"
RUN dotnet build "fsw-bug-poc.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "fsw-bug-poc.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENV DOTNET_USE_POLLING_FILE_WATCHER=true
RUN mkdir -p /app/Watched
VOLUME /app/Watched
ENTRYPOINT ["dotnet", "fsw-bug-poc.dll"]
According to this link adding ENV DOTNET_USE_POLLING_FILE_WATCHER=true
to the Dockerfile fixes the FileSystemWatcher not working inside the container.
Even with this fix, FileSystemWatcher will not work when running a Linux container on Windows and mounting a shared driver to a volume:
docker build -t fsw-bug-poc .
docker run -it --rm -v C:\Shared:/app/Watched fsw-bug-poc
Modifying a file inside the container:
Modifying files in the shared volume folder:
Nothing happens!!
Can someone explain what is going on? The FileSystemWatcher is using a polling strategy, so it should work the same way, shouldn't it?
The Linux implementation of FileSystemWatcher creates a new thread with its own inotify instance for every directory that's watched.
Use FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files and subdirectories of the specified directory. You can create a component to watch files on a local computer, a network drive, or a remote computer.
To stop the watcher from reporting changes then set its EnableRaisingEvents property to False. If you've finished with it then Dispose it. Your problem is that you haven't retained a reference to any of the FileSystemWatchers you've created.
Switching to PhysicalFileProvider.Watch did the job. It seems to be a more portable implementation for file system watching strategies.
The current implementation of PhysicalFileProvider
supports the DOTNET_USE_POLLING_FILE_WATCHER
environment variable. I couldn't find any reference of it in FileSystemWatcher
implementation.
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using System;
using System.IO;
namespace fsw_bug_poc
{
class Program
{
private static PhysicalFileProvider _fileProvider;
private static IChangeToken _fileChangeToken;
static void Main(string[] args)
{
_fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "."));
WatchForFileChanges();
Console.ReadKey(false);
}
private static void WatchForFileChanges()
{
_fileChangeToken = _fileProvider.Watch("*.*");
_fileChangeToken.RegisterChangeCallback(Notify, default);
}
private static void Notify(object state)
{
Console.WriteLine("File change detected");
WatchForFileChanges();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With