Fix a crashing bug on Linux.
When a directory was removed immediately after a subdirectory was
created, the subdirectory event would be buffered. We'd then attempt
to watch the subdirectory even though the stream group was already
closed.
Fixed b/30768513.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aa6752e..c3acaf5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.9.7+3
+
+* Fix a crashing bug on Linux.
+
# 0.9.7+2
* Narrow the constraint on `async` to reflect the APIs this package is actually
diff --git a/lib/src/directory_watcher/linux.dart b/lib/src/directory_watcher/linux.dart
index f33a554..df1365c 100644
--- a/lib/src/directory_watcher/linux.dart
+++ b/lib/src/directory_watcher/linux.dart
@@ -66,18 +66,18 @@
: _files = new PathSet(path) {
_nativeEvents.add(new Directory(path).watch().transform(
new StreamTransformer.fromHandlers(handleDone: (sink) {
- // Once the root directory is deleted, no more new subdirectories will be
- // watched.
- _nativeEvents.close();
- sink.close();
+ // Handle the done event here rather than in the call to [_listen] because
+ // [innerStream] won't close until we close the [StreamGroup]. However, if
+ // we close the [StreamGroup] here, we run the risk of new-directory
+ // events being fired after the group is closed, since batching delays
+ // those events. See b/30768513.
+ _onDone();
})));
// Batch the inotify changes together so that we can dedup events.
var innerStream = _nativeEvents.stream
.transform(new BatchedStreamTransformer<FileSystemEvent>());
- _listen(innerStream, _onBatch,
- onError: _eventsController.addError,
- onDone: _onDone);
+ _listen(innerStream, _onBatch, onError: _eventsController.addError);
_listen(new Directory(path).list(recursive: true), (entity) {
if (entity is Directory) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 57e75e6..35b6517 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: watcher
-version: 0.9.7+2
+version: 0.9.8-dev
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/watcher
description: >
diff --git a/test/directory_watcher/shared.dart b/test/directory_watcher/shared.dart
index c95ee39..148eee2 100644
--- a/test/directory_watcher/shared.dart
+++ b/test/directory_watcher/shared.dart
@@ -92,6 +92,23 @@
]);
});
+ // Regression test for b/30768513.
+ test("doesn't crash when the directory is moved immediately after a subdir "
+ "is added", () {
+ writeFile("dir/a.txt");
+ writeFile("dir/b.txt");
+
+ startWatcher(path: "dir");
+
+ createDir("dir/subdir");
+ renameDir("dir", "moved_dir");
+ createDir("dir");
+ inAnyOrder([
+ isRemoveEvent("dir/a.txt"),
+ isRemoveEvent("dir/b.txt")
+ ]);
+ });
+
group("moves", () {
test('notifies when a file is moved within the watched directory', () {
writeFile("old.txt");