Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pkgs/watcher/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
9 changes: 8 additions & 1 deletion pkgs/watcher/lib/src/directory_watcher/windows.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,14 @@ class _WindowsDirectoryWatcher
});
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) {
Expand Down
2 changes: 1 addition & 1 deletion pkgs/watcher/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
46 changes: 46 additions & 0 deletions pkgs/watcher/test/directory_watcher/windows_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,52 @@ void main() {
},
);

// 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
Expand Down
Loading