add better error handling when stdin gives an error instead of EOF
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd62957..d81018c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.1.2
+
+* Add better handling for the case where stdin gives an error instead of an EOF.
+
## 0.1.1
* Export `AsyncMessageGrouper` and `SyncMessageGrouper` as part of the testing
diff --git a/lib/src/async_message_grouper.dart b/lib/src/async_message_grouper.dart
index 448f51e..93caf49 100644
--- a/lib/src/async_message_grouper.dart
+++ b/lib/src/async_message_grouper.dart
@@ -27,19 +27,26 @@
/// Returns the next full message that is received, or null if none are left.
Future<List<int>> get next async {
- List<int> message;
- while (
- message == null && (_buffer.isNotEmpty || await _inputQueue.hasNext)) {
- if (_buffer.isEmpty) _buffer.addAll(await _inputQueue.next);
- var nextByte = _buffer.removeFirst();
- if (nextByte == -1) return null;
- message = _state.handleInput(nextByte);
+ try {
+ List<int> message;
+ while (message == null &&
+ (_buffer.isNotEmpty || await _inputQueue.hasNext)) {
+ if (_buffer.isEmpty) _buffer.addAll(await _inputQueue.next);
+ var nextByte = _buffer.removeFirst();
+ if (nextByte == -1) return null;
+ message = _state.handleInput(nextByte);
+ }
+
+ // If there is nothing left in the queue then cancel the subscription.
+ if (message == null) _inputQueue.cancel();
+
+ return message;
+ } catch (e) {
+ // It appears we sometimes get an exception instead of -1 as expected when
+ // stdin closes, this handles that in the same way (returning a null
+ // message)
+ return null;
}
-
- // If there is nothing left in the queue then cancel the subscription.
- if (message == null) _inputQueue.cancel();
-
- return message;
}
/// Stop listening to the stream for further updates.
diff --git a/lib/src/sync_message_grouper.dart b/lib/src/sync_message_grouper.dart
index 50d5dca..20a1139 100644
--- a/lib/src/sync_message_grouper.dart
+++ b/lib/src/sync_message_grouper.dart
@@ -18,12 +18,19 @@
///
/// Returns null at end of file.
List<int> get next {
- List<int> message;
- while (message == null) {
- var nextByte = _stdin.readByteSync();
- if (nextByte == -1) return null;
- message = _state.handleInput(nextByte);
+ try {
+ List<int> message;
+ while (message == null) {
+ var nextByte = _stdin.readByteSync();
+ if (nextByte == -1) return null;
+ message = _state.handleInput(nextByte);
+ }
+ return message;
+ } catch (e) {
+ // It appears we sometimes get an exception instead of -1 as expected when
+ // stdin closes, this handles that in the same way (returning a null
+ // message)
+ return null;
}
- return message;
}
}
diff --git a/lib/testing.dart b/lib/testing.dart
index ecc3142..882097f 100644
--- a/lib/testing.dart
+++ b/lib/testing.dart
@@ -51,6 +51,7 @@
class TestStdinAsync implements TestStdin {
/// Controls the stream for async delivery of bytes.
final StreamController _controller = new StreamController();
+ StreamController get controller => _controller;
/// Adds all the [bytes] to this stream.
void addInputBytes(List<int> bytes) {
diff --git a/pubspec.yaml b/pubspec.yaml
index 241861f..e7e589e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: bazel_worker
-version: 0.1.1
+version: 0.1.2
description: Tools for creating a bazel persistent worker.
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/bazel_worker
diff --git a/test/message_grouper_test.dart b/test/message_grouper_test.dart
index 8a975fb..39dcb9e 100644
--- a/test/message_grouper_test.dart
+++ b/test/message_grouper_test.dart
@@ -137,4 +137,15 @@
[30, 40]
]);
});
+
+ test('Handles the case when stdin gives an error instead of EOF', () async {
+ if (stdinStream is TestStdinSync) {
+ // Reading will now cause an error as pendingBytes is empty.
+ (stdinStream as TestStdinSync).pendingBytes.clear();
+ expect(messageGrouper.next, isNull);
+ } else if (stdinStream is TestStdinAsync) {
+ (stdinStream as TestStdinAsync).controller.addError('Error!');
+ expect(await messageGrouper.next, isNull);
+ }
+ });
}
diff --git a/test/worker_loop_test.dart b/test/worker_loop_test.dart
index 1c27d5d..ac4dd11 100644
--- a/test/worker_loop_test.dart
+++ b/test/worker_loop_test.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:async';
import 'dart:io';
import 'package:test/test.dart';
@@ -35,7 +36,7 @@
TestWorkerLoop workerLoopFactory(/*=T*/ connection)) {
TestStdin stdinStream;
TestStdoutStream stdoutStream;
- var /*=T*/ connection;
+ var/*=T*/ connection;
TestWorkerLoop workerLoop;
setUp(() {
@@ -86,4 +87,17 @@
stdinStream.close();
await workerLoop.run();
});
+
+ test('Stops if stdin gives an error instead of EOF', () async {
+ if (stdinStream is TestStdinSync) {
+ // Reading will now cause an error as pendingBytes is empty.
+ (stdinStream as TestStdinSync).pendingBytes.clear();
+ await workerLoop.run();
+ } else if (stdinStream is TestStdinAsync) {
+ var done = new Completer();
+ workerLoop.run().then((_) => done.complete(null));
+ (stdinStream as TestStdinAsync).controller.addError('Error!!');
+ await done.future;
+ }
+ });
}