[Mono-dev] FileSystemWatcher Issue?

Rick Tillery rtillerywork at gmail.com
Mon Jul 31 16:46:42 UTC 2017

In conjunction with "Sync of mono Cert Store," I'm trying to utilize
FileSystemWatcher to monitor the system certificate file for changes (which
will trigger a cert-sync).

Since some distros use the legacy address
(/etc/pki/tls/certs/ca-bundle.crt) as a symbolic link, and modification of
the system cert store appears to be a free-for-all between using the
update-ca-trust <http://www.unix.com/man-page/centos/8/update-ca-trust/> or
scripts, running other utilities
modifying the file directly
and even replacing the file completely
I have been testing as many file manipulation combinations as I can
imagine, to ensure FileSystemWatcher catches them all.

In doing so, I found an issue in FileSystemWatcher.

To handle the symbolic link case, FileSystemWatcher objects are set up for
each file in the chain, symbolic link and target alike.  In one test, the
target of a symbolic link is replaced by another file using mv.  But
FileSystemWatcher does not register the change.  Oddly, if only a watch of
the target file is registered, FileSystemWatcher registers the change.

The code I'm using is attached.  Here is what I see on command line:

(console1) ~$ echo >bar "test"
(console1) ~$ echo >foobar "test1"
(console1) ~$ ln -s bar foo
(console1) ~$ ll
total 24
-rw-rw-r--. 1 rtillery rtillery      5 Jul 31 11:06 bar
lrwxrwxrwx. 1 rtillery rtillery      3 Jul 31 11:06 foo -> bar
-rw-rw-r--. 1 rtillery rtillery      6 Jul 31 11:06 foobar
-rwxrwxr-x. 1 rtillery rtillery   5632 Jul 31 11:05 fsw.exe
(console1) ~$ mono fsw.exe ./bar
Watching: /home/rtillery/bar
bar watching ENABLED
Press 'Q' to quit

(console2) ~$ mv foobar bar

File: /home/rtillery/foobar renamed to /home/rtillery/bar


(console1) ~$ mono fsw.exe ./foo
Watching: /home/rtillery/foo
Watching: /home/rtillery/bar
foo watching ENABLED
bar watching ENABLED
Press 'Q' to quit

(console2) ~$ echo >foobar "test"
(console2) ~$ mv foobar bar

Nothing appears on console 1 in the second case, but I don't really see
why.  I believe I'm setting up the watches in exactly the same way, except
that there are two instead of one.  Is this a problem with
FileSystemWatcher?  Code is below.


using System;
using System.Collections.Generic;
using System.IO;
using Mono.Unix;

// Compile with "mcs fsw.cs /r:Mono.Posix.dll"

public class FSW
    private static IDictionary<string, FileSystemWatcher> watches = new
Dictionary<string, FileSystemWatcher>();

    public static void Main()
        string[] args = System.Environment.GetCommandLineArgs();
        if (args.Length != 2)
            System.Console.WriteLine("USAGE: (mono) fswtest(.exe)
            goto Error;


        Console.WriteLine("Press \'Q\' to quit.");
        while(Console.Read() != 'q')


    private static void SetUpWatch(string file)
            file = GetSymbolicLinkTarget(file);
        while (file != null);

    private static void AddWatch(string file)
        FileSystemWatcher watcher = new FileSystemWatcher();
        watcher.Path = Path.GetDirectoryName(file);
        watcher.NotifyFilter = 0
//          | NotifyFilters.Attributes
//          | NotifyFilters.CreationTime
          | NotifyFilters.DirectoryName
          | NotifyFilters.FileName
          | NotifyFilters.LastAccess
          | NotifyFilters.LastWrite
//          | NotifyFilters.Security
//          | NotifyFilters.Size
        watcher.Filter = Path.GetFileName(file);
        watcher.Changed += new FileSystemEventHandler(OnChanged);
        watcher.Created += new FileSystemEventHandler(OnChanged);
        watcher.Deleted += new FileSystemEventHandler(OnChanged);
//        watcher.Disposed // Occurs when the component is disposed by a
call to the Dispose method. (Inherited from Component.)
//        watcher.Error // Occurs when the instance of FileSystemWatcher is
unable to continue monitoring changes or when the internal buffer overflows.
        watcher.Renamed += new RenamedEventHandler(OnRenamed);
        watches.Add(Path.GetFullPath(file), watcher);
Console.WriteLine("Watching: " + Path.GetFullPath(file));

    private static string GetSymbolicLinkTarget(string file)
        UnixSymbolicLinkInfo link = new UnixSymbolicLinkInfo(file);
        return link.HasContents ? link.GetContents().FullName : null;

    private static void EnableWatches()
        foreach (KeyValuePair<string, FileSystemWatcher> watch in watches)
            watch.Value.EnableRaisingEvents = true;
Console.WriteLine("" + watch.Value.Filter + " watching ENABLED");

    private static void OnChanged(object source, FileSystemEventArgs
        Console.WriteLine("File: \"" + eventargs.FullPath + "\" -- " +

    private static void OnRenamed(object source, RenamedEventArgs eventargs)
        Console.WriteLine("File: {0} renamed to {1}",
eventargs.OldFullPath, eventargs.FullPath);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.dot.net/pipermail/mono-devel-list/attachments/20170731/997ad9f2/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fsw.cs
Type: text/x-csharp
Size: 2980 bytes
Desc: not available
URL: <http://lists.dot.net/pipermail/mono-devel-list/attachments/20170731/997ad9f2/attachment.bin>

More information about the Mono-devel-list mailing list