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
3 changes: 3 additions & 0 deletions pkgs/watcher/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
- Improve handling of subdirectories: ignore `PathNotFoundException` due to
subdirectory deletion racing with watcher internals, instead of raising
it on the event stream.
- Improve handling of watcher overflow on Windows: prepare for future versions
of SDK, which will properly forward `FileSystemException` into the stream
returned by the watcher.

## 1.1.3

Expand Down
43 changes: 25 additions & 18 deletions pkgs/watcher/lib/src/directory_watcher/windows.dart
Original file line number Diff line number Diff line change
Expand Up @@ -405,35 +405,42 @@ class _WindowsDirectoryWatcher

/// Start or restart the underlying [Directory.watch] stream.
void _startWatch() {
// Note: "watcher closed" exceptions do not get sent over the stream
// returned by watch, and must be caught via a zone handler.
// Note: in older SDKs "watcher closed" exceptions might not get sent over
// the stream returned by watch, and must be caught via a zone handler.
runZonedGuarded(
() {
var innerStream = Directory(path).watch(recursive: true);
_watchSubscription = innerStream.listen(
_onEvent,
onError: _eventsController.addError,
onError: _restartWatchOnOverflowOr(_eventsController.addError),
onDone: _onDone,
);
},
(error, stackTrace) async {
if (error is FileSystemException &&
error.message.startsWith('Directory watcher closed unexpectedly')) {
// Wait to work around https://github.com/dart-lang/sdk/issues/61378.
// Give the VM time to reset state after the error. See the issue for
// more discussion of the workaround.
await _watchSubscription?.cancel();
await Future<void>.delayed(const Duration(milliseconds: 1));
_eventsController.addError(error, stackTrace);
_startWatch();
} else {
// ignore: only_throw_errors
throw error;
}
},
_restartWatchOnOverflowOr((error, stackTrace) {
// ignore: only_throw_errors
throw error;
}),
);
}

void Function(Object, StackTrace) _restartWatchOnOverflowOr(
void Function(Object, StackTrace) otherwise) {
return (Object error, StackTrace stackTrace) async {
if (error is FileSystemException &&
error.message.startsWith('Directory watcher closed unexpectedly')) {
// Wait to work around https://github.com/dart-lang/sdk/issues/61378.
// Give the VM time to reset state after the error. See the issue for
// more discussion of the workaround.
await _watchSubscription?.cancel();
await Future<void>.delayed(const Duration(milliseconds: 1));
_eventsController.addError(error, stackTrace);
_startWatch();
} else {
otherwise(error, stackTrace);
}
};
}

/// Starts or restarts listing the watched directory to get an initial picture
/// of its state.
Future<void> _listDir() {
Expand Down