Merge branch 'master' into new-package-config
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32f9830..c3d28d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,14 @@
-## 0.13.7 - 2020-02-14
+## 0.13.8 - 2020-03-02
 
 * Update to package_config `1.9.0` which supports package_config.json
   files and should be forwards compatible with `2.0.0`.
 * Deprecate the `packageRoot` argument on `Resolver`.
 
+## 0.13.7 - 2020-02-28
+
+* Loosen the dependency on the `vm_service` package from `>=1.0.0 <3.0.0` to
+`>=1.0.0 <4.0.0`.
+
 ## 0.13.6 - 2020-02-10
 
 * Now consider all `.json` files for the `format_coverage` command.
diff --git a/lib/src/collect.dart b/lib/src/collect.dart
index f44b030..768e2f8 100644
--- a/lib/src/collect.dart
+++ b/lib/src/collect.dart
@@ -51,7 +51,10 @@
       final options = const CompressionOptions(enabled: false);
       final socket = await WebSocket.connect('$uri', compression: options);
       final controller = StreamController<String>();
-      socket.listen((data) => controller.add(data as String));
+      socket.listen((data) => controller.add(data as String), onDone: () {
+        controller.close();
+        service.dispose();
+      });
       service = VmService(
           controller.stream, (String message) => socket.add(message),
           log: StdoutLog(), disposeHandler: () => socket.close());
@@ -86,7 +89,7 @@
     if (isolateIds != null && !isolateIds.contains(isolateRef.id)) continue;
     if (scopedOutput.isNotEmpty) {
       final scripts = await service.getScripts(isolateRef.id);
-      for (var script in scripts.scripts) {
+      for (ScriptRef script in scripts.scripts) {
         final uri = Uri.parse(script.uri);
         if (uri.scheme != 'package') continue;
         final scope = uri.path.split('/').first;
@@ -94,7 +97,7 @@
         if (!scopedOutput.contains(scope)) continue;
         final scriptReport = await service.getSourceReport(
             isolateRef.id, <String>[SourceReportKind.kCoverage],
-            forceCompile: true, scriptId: script.id);
+            forceCompile: true, scriptId: script.id) as SourceReport;
         final coverage = await _getCoverageJson(
             service, isolateRef, scriptReport, includeDart);
         allCoverage.addAll(coverage);
@@ -104,7 +107,7 @@
         isolateRef.id,
         <String>[SourceReportKind.kCoverage],
         forceCompile: true,
-      );
+      ) as SourceReport;
       final coverage = await _getCoverageJson(
           service, isolateRef, isolateReport, includeDart);
       allCoverage.addAll(coverage);
@@ -115,11 +118,22 @@
 
 Future _resumeIsolates(VmService service) async {
   final vm = await service.getVM();
+  final futures = <Future>[];
   for (var isolateRef in vm.isolates) {
-    final isolate = await service.getIsolate(isolateRef.id) as Isolate;
-    if (isolate.pauseEvent.kind != EventKind.kResume) {
-      await service.resume(isolateRef.id);
-    }
+    // Guard against sync as well as async errors: sync - when we are writing
+    // message to the socket, the socket might be closed; async - when we are
+    // waiting for the response, the socket again closes.
+    futures.add(Future.sync(() async {
+      final isolate = await service.getIsolate(isolateRef.id) as Isolate;
+      if (isolate.pauseEvent.kind != EventKind.kResume) {
+        await service.resume(isolateRef.id);
+      }
+    }));
+  }
+  try {
+    await Future.wait(futures);
+  } catch (_) {
+    // Ignore resume isolate failures
   }
 }
 
diff --git a/pubspec.yaml b/pubspec.yaml
index 45b1e64..5401403 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: coverage
-version: 0.13.7
+version: 0.13.8
 description: Coverage data manipulation and formatting
 homepage: https://github.com/dart-lang/coverage
 
@@ -13,7 +13,7 @@
   path: '>=0.9.0 <2.0.0'
   source_maps: ^0.10.8
   stack_trace: ^1.3.0
-  vm_service: '>=1.0.0 <3.0.0'
+  vm_service: '>=1.0.0 <4.0.0'
 
 dev_dependencies:
   pedantic: ^1.0.0