List directory failure (#2151)
diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md
index b4727e5..30a1975 100644
--- a/pkgs/watcher/CHANGELOG.md
+++ b/pkgs/watcher/CHANGELOG.md
@@ -1,10 +1,12 @@
-## 1.1.3-wip
+## 1.1.3
- Improve handling of
`FileSystemException: Directory watcher closed unexpectedly` on Windows. The
watcher was already attempting to restart after this error and resume sending
events. But, the restart would sometimes silently fail. Now, it is more
reliable.
+- Improving handling of directories that are created then immediately deleted on
+ Windows. Previously, that could cause a `PathNotfoundException` to be thrown.
## 1.1.2
diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart
index 6d88e65..8f21268 100644
--- a/pkgs/watcher/lib/src/directory_watcher/windows.dart
+++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart
@@ -198,7 +198,14 @@
});
subscription.onError((Object e, StackTrace stackTrace) {
_listSubscriptions.remove(subscription);
- _emitError(e, stackTrace);
+ // "Path not found" can be caused by creating then quickly removing
+ // a directory: continue without reporting an error. Nested files
+ // that get removed during the `list` are already ignored by `list`
+ // itself, so there are no other types of "path not found" that
+ // might need different handling here.
+ if (e is! PathNotFoundException) {
+ _emitError(e, stackTrace);
+ }
});
_listSubscriptions.add(subscription);
} else if (event is FileSystemModifyEvent) {
diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml
index bccdfac..16af27b 100644
--- a/pkgs/watcher/pubspec.yaml
+++ b/pkgs/watcher/pubspec.yaml
@@ -1,5 +1,5 @@
name: watcher
-version: 1.1.3-wip
+version: 1.1.3
description: >-
A file system watcher. It monitors changes to contents of directories and
sends notifications when files have been added, removed, or modified.
diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart
index a6bc14d..6489771 100644
--- a/pkgs/watcher/test/directory_watcher/windows_test.dart
+++ b/pkgs/watcher/test/directory_watcher/windows_test.dart
@@ -66,6 +66,52 @@
},
);
+ // Regression test for https://github.com/dart-lang/tools/issues/2152:
+ // watcher can throws if a directory is created then quickly deleted.
+ group('Transient directory', () {
+ late StreamSubscription<Object> subscription;
+ late Directory temp;
+ late Watcher watcher;
+ late int errorsSeen;
+
+ setUp(() async {
+ temp = Directory.systemTemp.createTempSync();
+ watcher = DirectoryWatcher(temp.path);
+ errorsSeen = 0;
+ subscription = watcher.events.listen(
+ (e) {},
+ onError: (Object e, _) {
+ print('Event stream error: $e');
+ ++errorsSeen;
+ },
+ );
+ await watcher.ready;
+ });
+
+ tearDown(() {
+ subscription.cancel();
+ });
+
+ test('does not break watching', () async {
+ // Iterate creating 10 directories and deleting 1-10 of them. This means
+ // the directories will exist for different lengths of times, exploring
+ // possible race conditions in directory handling.
+ for (var i = 0; i != 50; ++i) {
+ for (var j = 0; j != 10; ++j) {
+ File('${temp.path}\\$j\\file').createSync(recursive: true);
+ }
+ await Future<void>.delayed(const Duration(milliseconds: 1));
+ for (var j = 0; j != i % 10 + 1; ++j) {
+ final d = Directory('${temp.path}\\$j');
+ d.deleteSync(recursive: true);
+ }
+ await Future<void>.delayed(const Duration(milliseconds: 1));
+ }
+
+ expect(errorsSeen, 0);
+ });
+ });
+
// The Windows native watcher has a buffer that gets exhausted if events are
// not handled quickly enough. Then, it throws an error and stops watching.
// The exhaustion is reliably triggered if enough events arrive during a sync