Fix bugs where events could be added after watchers were closed.

R=rnystrom@google.com
BUG=dartbug.com/22653

Review URL: https://codereview.chromium.org//995623002
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2ff887e..7772980 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.9.5
+
+* Fix bugs where events could be added after watchers were closed.
+
 # 0.9.4
 
 * Treat add events for known files as modifications instead of discarding them
diff --git a/lib/src/directory_watcher/linux.dart b/lib/src/directory_watcher/linux.dart
index 76558dd..870faa7 100644
--- a/lib/src/directory_watcher/linux.dart
+++ b/lib/src/directory_watcher/linux.dart
@@ -134,7 +134,7 @@
       if (isReady) _eventsController.add(event);
     }, onError: (error, stackTrace) {
       _eventsController.addError(error, stackTrace);
-      _eventsController.close();
+      close();
     }, onDone: () {
       if (_subWatchers[path] == watcher) _subWatchers.remove(path);
 
diff --git a/lib/src/directory_watcher/mac_os.dart b/lib/src/directory_watcher/mac_os.dart
index ee20136..c242c75 100644
--- a/lib/src/directory_watcher/mac_os.dart
+++ b/lib/src/directory_watcher/mac_os.dart
@@ -69,9 +69,9 @@
   /// the directory to determine its initial state.
   StreamSubscription<FileSystemEntity> _initialListSubscription;
 
-  /// The subscription to the [Directory.list] call for listing the contents of
-  /// a subdirectory that was moved into the watched directory.
-  StreamSubscription<FileSystemEntity> _listSubscription;
+  /// The subscriptions to [Directory.list] calls for listing the contents of a
+  /// subdirectory that was moved into the watched directory.
+  final _listSubscriptions = new Set<StreamSubscription<FileSystemEntity>>();
 
   /// The timer for tracking how long we wait for an initial batch of bogus
   /// events (see issue 14373).
@@ -113,10 +113,14 @@
     }
     if (_watchSubscription != null) _watchSubscription.cancel();
     if (_initialListSubscription != null) _initialListSubscription.cancel();
-    if (_listSubscription != null) _listSubscription.cancel();
     _watchSubscription = null;
     _initialListSubscription = null;
-    _listSubscription = null;
+
+    for (var subscription in _listSubscriptions) {
+      subscription.cancel();
+    }
+    _listSubscriptions.clear();
+
     _eventsController.close();
   }
 
@@ -194,8 +198,9 @@
 
           if (_files.containsDir(path)) continue;
 
-          var stream = Chain.track(new Directory(path).list(recursive: true));
-          _listSubscription = stream.listen((entity) {
+          var subscription;
+          subscription = Chain.track(new Directory(path).list(recursive: true))
+              .listen((entity) {
             if (entity is Directory) return;
             if (_files.contains(path)) return;
 
@@ -206,7 +211,10 @@
               print("[$_id] got error listing $relativePath: $e");
             }
             _emitError(e, stackTrace);
+          }, onDone: () {
+            _listSubscriptions.remove(subscription);
           }, cancelOnError: true);
+          _listSubscriptions.add(subscription);
         } else if (event is FileSystemModifyEvent) {
           assert(!event.isDirectory);
           _emitEvent(ChangeType.MODIFY, path);
diff --git a/pubspec.yaml b/pubspec.yaml
index c0c71eb..a16a020 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: watcher
-version: 0.9.4
+version: 0.9.5
 author: Dart Team <misc@dartlang.org>
 homepage: http://github.com/dart-lang/watcher
 description: >