attempt to parse invalid protos as strings (#8)
diff --git a/lib/src/driver/driver_connection.dart b/lib/src/driver/driver_connection.dart
index 787fcfd..b170586 100644
--- a/lib/src/driver/driver_connection.dart
+++ b/lib/src/driver/driver_connection.dart
@@ -3,10 +3,12 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:convert';
import 'dart:io';
import '../async_message_grouper.dart';
import '../worker_protocol.pb.dart';
+import '../constants.dart';
import '../utils.dart';
/// A connection from a `BazelWorkerDriver` to a worker.
@@ -35,12 +37,35 @@
new StdDriverConnection(
inputStream: worker.stdout, outputStream: worker.stdin);
+ /// Note: This will attempts to recover from invalid proto messages by parsing
+ /// them as strings. This is a common error case for workers (they print a
+ /// message to stdout on accident). This isn't perfect however as it only
+ /// happens if the parsing throws, you can still hang indefinitely if the
+ /// [MessageGrouper] doesn't find what it thinks is the end of a proto
+ /// message.
@override
Future<WorkResponse> readResponse() async {
var buffer = await _messageGrouper.next;
if (buffer == null) return null;
- return new WorkResponse.fromBuffer(buffer);
+ WorkResponse response;
+ try {
+ response = new WorkResponse.fromBuffer(buffer);
+ } catch (_) {
+ try {
+ // Try parsing the message as a string and set that as the output.
+ var output = UTF8.decode(buffer);
+ var response = new WorkResponse()
+ ..exitCode = EXIT_CODE_ERROR
+ ..output = 'Worker sent an invalid response:\n$output';
+ return response;
+ } catch (_) {
+ // Fall back to original exception and rethrow if we fail to parse as
+ // a string.
+ }
+ rethrow;
+ }
+ return response;
}
@override