Skip to content

FileSystemWatcher doesn't trigger Deleted event for file when watched directory is deleted on OSX #44484

Closed

Description

@ericstj

Description

Create a FileSystemWatcher that watches a directory.
Create a file in that directory and observe Created event.
Delete the file and observe Deleted event.
Create another file in that directory and observe Created event.
Delete the directory, and no deleted event ever arrives.

Configuration

  • Which version of .NET is the code running on? .NET 5.0
  • What OS and version, and what distro if applicable? OSX 10.13.6
  • What is the architecture (x64, x86, ARM, ARM64)? x64
  • Do you know whether it is specific to that configuration? It appears to be specific to OSX

Regression?

Not a regression, but different than other platforms

Other information

May be similar to #30415
Discovered when working on #41426

Repro:

using System;
using System.IO;
using System.Threading.Tasks;


namespace fileWatch
{
    class Program
    {
        static async Task Main(string[] args)
        {
            int waitTime = 1000;
            var rootPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            var subDir = Path.Combine(rootPath, "sub");
            
            Directory.CreateDirectory(rootPath);
            Directory.CreateDirectory(subDir);

            using (var fsw = new FileSystemWatcher(rootPath, "*"))
            {
                fsw.Created += (o, e) => Console.WriteLine($"Created {e.FullPath}");
                fsw.Deleted += (o, e) => Console.WriteLine($"Deleted {e.FullPath}");
                fsw.IncludeSubdirectories = true;
                fsw.EnableRaisingEvents = true;

                var fileLocation = Path.Combine(subDir, Path.GetRandomFileName());
                File.WriteAllText(fileLocation, "temp");
                await Task.Delay(waitTime);
                File.Delete(fileLocation);
                await Task.Delay(waitTime);

                fileLocation = Path.Combine(subDir, Path.GetRandomFileName());
                File.WriteAllText(fileLocation, "temp");
                await Task.Delay(waitTime);
                Directory.Delete(subDir, true);
                await Task.Delay(waitTime);

                fileLocation = Path.Combine(rootPath, Path.GetRandomFileName());
                File.WriteAllText(fileLocation, "temp");
                await Task.Delay(waitTime);
                File.Delete(fileLocation);
                await Task.Delay(waitTime);

                fileLocation = Path.Combine(rootPath, Path.GetRandomFileName());
                File.WriteAllText(fileLocation, "temp");
                await Task.Delay(waitTime);
                Directory.Delete(rootPath, true);
                await Task.Delay(waitTime);
                Console.WriteLine(File.Exists(fileLocation));
            }
        }
    }
}

Activity

  1. ericstj commented on Nov 10, 2020

    @ericstj
    MemberAuthor

    This appears to be unique to only when the root-level watched directory is removed. If a directory underneath the root directory is removed then the deleted event is observed. I've updated the sample above to better illustrate this.

  2. added
    untriagedNew issue has not been triaged by the area owner
    on Nov 10, 2020
  3. carlossanlop commented on Nov 14, 2020

    @carlossanlop
    Contributor

    Delete the directory, and no deleted event ever arrives.

    It was my understanding that FileSystemWatcher does not watch changes in the monitored directory itself, only on the files and directories inside it.

    I remembered that fact from this closed issue, from which I learned that not even Windows reports events from the monitored directory itself. That is how the behavior is described in the Windows API we invoke: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-readdirectorychangesw

  4. removed
    untriagedNew issue has not been triaged by the area owner
    on Nov 14, 2020
  5. jozkee commented on Nov 14, 2020

    @jozkee
    Member

    Not a regression, but different than other platforms

    @ericstj the sample you provided behaves similar to what you describe on Windows and Linux, is there something that I am missing?
    This is the output that I get:

    Created C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\sub\4fo3tpfq.nwd
    Deleted C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\sub\4fo3tpfq.nwd
    Created C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\sub\pboshy2t.kar
    Deleted C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\sub\pboshy2t.kar
    Deleted C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\sub
    Created C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\k2lg0a3p.kyq
    Deleted C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\k2lg0a3p.kyq
    Created C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\2mjivqn4.qf5
    Deleted C:\Users\dacantu\AppData\Local\Temp\rr05f1lh.mdy\2mjivqn4.qf5
    False
    
  6. ericstj commented on Nov 14, 2020

    @ericstj
    MemberAuthor

    This failure is specific to Mac (OSX) which uses a different implementation. On Mac the last deleted event will be missing.

  7. jozkee commented on Nov 16, 2020

    @jozkee
    Member

    I see now, it is reporting Create twice and not reporting Delete when you erase the root as you mentioned:

    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub/noozqidc.ibi
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub/noozqidc.ibi
    Deleted /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub/noozqidc.ibi
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub/ibmlfqwy.nie
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub/ibmlfqwy.nie
    Deleted /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub/ibmlfqwy.nie
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub
    Deleted /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/sub
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/xbdmmr50.et3
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/xbdmmr50.et3
    Deleted /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/xbdmmr50.et3
    Created /var/folders/gz/6z3dn8kn20g5wlk7rt7cs0h40000gq/T/xltqrcpx.vdv/xxfnco43.dmg
    False
    
  8. added this to the Future milestone on Nov 16, 2020
  9. dotnet-policy-service commented on May 18, 2025

    @dotnet-policy-service
    Contributor

    Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

    This process is part of our issue cleanup automation.

  10. dotnet-policy-service commented on Jun 2, 2025

    @dotnet-policy-service
    Contributor

    This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.

  11. removed this from the Future milestone on Jun 2, 2025
  12. locked and limited conversation to collaborators on Jul 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions