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

Windows: Cannot delete watched folder with not-empty subfolder #422

Closed
MajorBreakfast opened this issue Dec 28, 2015 · 9 comments
Closed

Comments

@MajorBreakfast
Copy link
Contributor

I noticed that I cannot delete a watched folder that has a not-empty subfolder on Windows. Here're two examples:

  1. I create the file a/b/c.txt. Chokidar picks up the change just fine. Then, I try to delete a/. This curiously doesn't work. Workaround: First delete a/b/, then delete a/.
  2. The same goes for folders: I create a/b/c/. Directly deleting a/ fails. Deleting a/b/ first, then a/ works.

Is this a known issue? Can it be fixed?

@paulmillr
Copy link
Owner

Have you tried switching the usePolling option?

@MajorBreakfast
Copy link
Contributor Author

Yes, it works with polling, but it also leads to 20% CPU usage vs 0% (7000 files).

@MajorBreakfast
Copy link
Contributor Author

I found the problem: My experiments show that on Windows you cannot delete a folder if it has a subfolder that is being watched inside. A possible solution would be to use fs.watch('path', { recursive: true }) and only watch the root folder.

I've spent the last week developing my own watcher which uses this approach. Two things I've learned (if you're interested):

  • The recursive option is a real time saver. My watcher's initial scan takes 340ms instead of 450ms for my 7000 files on Windows if I enable it. Naturally the watcher is able to detect deep changes in both modes.
  • I didn't need fsevents as a dependency to make everything work. fs.watch uses FSEvents for folders on Mac OS anyway and I'm only watching a single folder. So no ulimit issues.

I'm closing this. Enabling recursive mode is a major change for chokidar. Feel free to reopen if you decide to tackle it :)

@es128
Copy link
Contributor

es128 commented Jan 5, 2016

I do intend to work toward utilizing recursive: true for platforms that support it, but there will continue to be (legacy and current) platforms that do not, so it's more complex than simply adding the option and assuming it will work.

I also hope to eventually drop the fsevents optional dependency while leaving the handling code in place so users who prefer it have the option to add it themselves and use that watching mode. But I'd only consider that a viable possibility if the use of fs.watch on Mac can be made stable enough to mostly work out of the box, so that only a relatively small portion of users run into the kind of issues that would lead them to seek alternatively like installing fsevents directly.

Adding handler code for watchman and pathwatcher with the same approach (user needs to directly install the underlying module to utilize it) would be cool too - giving power users more options and control over their dependencies.

Anyway, all that is tangential to the original issue, which I'll leave closed because it's a Windows behavior relating to watched folders being considered in use that chokidar cannot do anything about. Users encountering this problem should close the watcher prior to deleting in this way.

@MajorBreakfast
Copy link
Contributor Author

I do intend to work toward utilizing recursive: true for platforms that support it, but there will continue to be (legacy and current) platforms that do not

Nice to hear! In my implementation I built a hierarchy of FolderHandler instances and each can be notified via the FolderHandler#notifyUnexplored() method. In non-recursive watching mode each FolderHandler has it's own watcher which calls the method. In recursive watching mode the root handler calls the method on the affected FolderHandler. Works reliably so far.

Anyway, what I'd like to ask: My watcher is barely a week old, so there's a change that I didn't encounter it yet - But why exactly doesn't fs.watch work on Mac OS? Sure, it's reporting is abysmally bad. For instance I'm getting rename events for file changes. But it does report paths and that suffices, does it not?

@es128
Copy link
Contributor

es128 commented Jan 5, 2016

The problem I've observed with it that I could not resolve with logic in chokidar was sporadic duplicate/phantom events - change events being the biggest problem. No reliable way to tell whether a change event on the same file 500ms later is a duplicate that should be suppressed or a legit new change. Seems to still happen on recent versions of node.

And since chokidar still aims to support versions prior to recursive being available, the low default ulimit on Mac is another substantial consideration.

Otherwise, it can be seen from the test suite passing that chokidar in fs.watch mode on Mac does do alright. But switching to it as the default mode has to be considered very carefully - if it causes issues for more people than fsevents does now, it would be a step backward.

@MajorBreakfast
Copy link
Contributor Author

Alright then. Great to hear :)

BTW here are some benchmark results for the inital scan (10 samples, 7800 entries):

Chokidar's average time is 3157.3ms
My watcher's average time with `recursive: true` is 201.7ms
My watcher's average time with `recursive: false` is 282.8ms

Note: Take this with a grain of salt. Although my watcher explores the same hierarchy, it has a lot less features, e.g. currently not even ignore patterns. However, I really wonder why the difference is so huge. Do you parallelize everything?

@es128
Copy link
Contributor

es128 commented Jan 6, 2016

What do you mean by "initial scan"? When I use that term it has little to do with the watching strategy - it's about walking the file tree to get a memory model of what's on disk. There's filtering type of stuff happening there too. At the moment that's done with readdirp, but that's another area that's going to be focused on for more optimization (see #412, for instance).

You haven't provided a link to or shown your code, so I don't really know what you're doing (or not doing) differently to have that perf impact. But if the stripped down approach is working better for you, great.

@MajorBreakfast
Copy link
Contributor Author

What do you mean by "initial scan"?

I mean the same thing. In the case of chokidar I measure the time between new FSWatcher({ cwd: 'data' }).add('.') and when the ready event fires.

You haven't provided a link to or shown your code

Jep and that's lousy. But it's part of a bigger project which I won't open-source until it's ready. If you really like to have a look, then this can be arranged though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants