Skip to content

Commit 654f334

Browse files
authored
Update watcher overflow detection (#2182)
Current versions of Dart SDK contain a bug: when watcher overflows on Windows it throws a synchronous exception instead of emitting an error into the stream. Newer versions of Dart SDK will fix this bug - but this means watcher restart code needs to be updated to be prepared for this.
1 parent 467df8c commit 654f334

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

pkgs/watcher/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
- Improve handling of subdirectories: ignore `PathNotFoundException` due to
44
subdirectory deletion racing with watcher internals, instead of raising
55
it on the event stream.
6+
- Improve handling of watcher overflow on Windows: prepare for future versions
7+
of SDK, which will properly forward `FileSystemException` into the stream
8+
returned by the watcher.
69

710
## 1.1.3
811

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

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -405,35 +405,42 @@ class _WindowsDirectoryWatcher
405405

406406
/// Start or restart the underlying [Directory.watch] stream.
407407
void _startWatch() {
408-
// Note: "watcher closed" exceptions do not get sent over the stream
409-
// returned by watch, and must be caught via a zone handler.
408+
// Note: in older SDKs "watcher closed" exceptions might not get sent over
409+
// the stream returned by watch, and must be caught via a zone handler.
410410
runZonedGuarded(
411411
() {
412412
var innerStream = Directory(path).watch(recursive: true);
413413
_watchSubscription = innerStream.listen(
414414
_onEvent,
415-
onError: _eventsController.addError,
415+
onError: _restartWatchOnOverflowOr(_eventsController.addError),
416416
onDone: _onDone,
417417
);
418418
},
419-
(error, stackTrace) async {
420-
if (error is FileSystemException &&
421-
error.message.startsWith('Directory watcher closed unexpectedly')) {
422-
// Wait to work around https://github.com/dart-lang/sdk/issues/61378.
423-
// Give the VM time to reset state after the error. See the issue for
424-
// more discussion of the workaround.
425-
await _watchSubscription?.cancel();
426-
await Future<void>.delayed(const Duration(milliseconds: 1));
427-
_eventsController.addError(error, stackTrace);
428-
_startWatch();
429-
} else {
430-
// ignore: only_throw_errors
431-
throw error;
432-
}
433-
},
419+
_restartWatchOnOverflowOr((error, stackTrace) {
420+
// ignore: only_throw_errors
421+
throw error;
422+
}),
434423
);
435424
}
436425

426+
void Function(Object, StackTrace) _restartWatchOnOverflowOr(
427+
void Function(Object, StackTrace) otherwise) {
428+
return (Object error, StackTrace stackTrace) async {
429+
if (error is FileSystemException &&
430+
error.message.startsWith('Directory watcher closed unexpectedly')) {
431+
// Wait to work around https://github.com/dart-lang/sdk/issues/61378.
432+
// Give the VM time to reset state after the error. See the issue for
433+
// more discussion of the workaround.
434+
await _watchSubscription?.cancel();
435+
await Future<void>.delayed(const Duration(milliseconds: 1));
436+
_eventsController.addError(error, stackTrace);
437+
_startWatch();
438+
} else {
439+
otherwise(error, stackTrace);
440+
}
441+
};
442+
}
443+
437444
/// Starts or restarts listing the watched directory to get an initial picture
438445
/// of its state.
439446
Future<void> _listDir() {

0 commit comments

Comments
 (0)