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");