Skip to content

Commit 24707e0

Browse files
authored
List directory failure (#2151)
1 parent 53a9f83 commit 24707e0

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

pkgs/watcher/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
## 1.1.3-wip
1+
## 1.1.3
22

33
- Improve handling of
44
`FileSystemException: Directory watcher closed unexpectedly` on Windows. The
55
watcher was already attempting to restart after this error and resume sending
66
events. But, the restart would sometimes silently fail. Now, it is more
77
reliable.
8+
- Improving handling of directories that are created then immediately deleted on
9+
Windows. Previously, that could cause a `PathNotfoundException` to be thrown.
810

911
## 1.1.2
1012

pkgs/watcher/lib/src/directory_watcher/windows.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,14 @@ class _WindowsDirectoryWatcher
198198
});
199199
subscription.onError((Object e, StackTrace stackTrace) {
200200
_listSubscriptions.remove(subscription);
201-
_emitError(e, stackTrace);
201+
// "Path not found" can be caused by creating then quickly removing
202+
// a directory: continue without reporting an error. Nested files
203+
// that get removed during the `list` are already ignored by `list`
204+
// itself, so there are no other types of "path not found" that
205+
// might need different handling here.
206+
if (e is! PathNotFoundException) {
207+
_emitError(e, stackTrace);
208+
}
202209
});
203210
_listSubscriptions.add(subscription);
204211
} else if (event is FileSystemModifyEvent) {

pkgs/watcher/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: watcher
2-
version: 1.1.3-wip
2+
version: 1.1.3
33
description: >-
44
A file system watcher. It monitors changes to contents of directories and
55
sends notifications when files have been added, removed, or modified.

pkgs/watcher/test/directory_watcher/windows_test.dart

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,52 @@ void main() {
6666
},
6767
);
6868

69+
// Regression test for https://github.com/dart-lang/tools/issues/2152:
70+
// watcher can throws if a directory is created then quickly deleted.
71+
group('Transient directory', () {
72+
late StreamSubscription<Object> subscription;
73+
late Directory temp;
74+
late Watcher watcher;
75+
late int errorsSeen;
76+
77+
setUp(() async {
78+
temp = Directory.systemTemp.createTempSync();
79+
watcher = DirectoryWatcher(temp.path);
80+
errorsSeen = 0;
81+
subscription = watcher.events.listen(
82+
(e) {},
83+
onError: (Object e, _) {
84+
print('Event stream error: $e');
85+
++errorsSeen;
86+
},
87+
);
88+
await watcher.ready;
89+
});
90+
91+
tearDown(() {
92+
subscription.cancel();
93+
});
94+
95+
test('does not break watching', () async {
96+
// Iterate creating 10 directories and deleting 1-10 of them. This means
97+
// the directories will exist for different lengths of times, exploring
98+
// possible race conditions in directory handling.
99+
for (var i = 0; i != 50; ++i) {
100+
for (var j = 0; j != 10; ++j) {
101+
File('${temp.path}\\$j\\file').createSync(recursive: true);
102+
}
103+
await Future<void>.delayed(const Duration(milliseconds: 1));
104+
for (var j = 0; j != i % 10 + 1; ++j) {
105+
final d = Directory('${temp.path}\\$j');
106+
d.deleteSync(recursive: true);
107+
}
108+
await Future<void>.delayed(const Duration(milliseconds: 1));
109+
}
110+
111+
expect(errorsSeen, 0);
112+
});
113+
});
114+
69115
// The Windows native watcher has a buffer that gets exhausted if events are
70116
// not handled quickly enough. Then, it throws an error and stops watching.
71117
// The exhaustion is reliably triggered if enough events arrive during a sync

0 commit comments

Comments
 (0)