From d28530dc87df34ba485e02efe1e3800a04e8ce37 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 5 Apr 2017 12:16:27 -0700 Subject: [PATCH] attempt to parse invalid protos as strings (#8) --- lib/src/driver/driver_connection.dart | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) 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 @@ class StdDriverConnection implements DriverConnection { 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 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