From 405b98d5efae38d57cda587a66db632b1cca0472 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Thu, 5 Jan 2017 13:59:56 -0400 Subject: [PATCH] fix(GUI): multiple JSON objects coming up at once from the IPC client (#997) The GUI executes the CLI and pipes every line of output coming from either `stdout` or `stderr` to the IPC server as "messages." In some scenarios, the child process data handler might receive multiple lines of output at the same time. Since the CLI outputs stringified JSON objects each in a different line, trying to parse two JSON objects separated by a new line causes the parser to crash. As a solution, we split the data coming in by new lines (`\r\n` in Windows), and emit a message for only the last one. Fixes: https://github.com/resin-io/etcher/issues/898 Changelog-Entry: Fix "Invalid message" error caused by the IPC client emitting multiple JSON objects as a single message. Change-Type: patch Signed-off-by: Juan Cruz Viotti --- lib/src/child-writer/writer-proxy.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/src/child-writer/writer-proxy.js b/lib/src/child-writer/writer-proxy.js index c8c4fd9c..e9523d82 100644 --- a/lib/src/child-writer/writer-proxy.js +++ b/lib/src/child-writer/writer-proxy.js @@ -157,7 +157,21 @@ return isElevated().then((elevated) => { child.on('close', resolve); const emitMessage = (data) => { - ipc.of[process.env.IPC_SERVER_ID].emit('message', data.toString()); + + // Output from stdout/stderr coming from the CLI might be buffered, + // causing several progress lines to come up at once as single message. + // Trying to parse multiple JSON objects separated by new lines will + // of course make the parser confused, causing errors later on. + // + // As a solution, we split the data coming in from the CLI into + // separate lines, and only emit a "message" event for the last one. + // + // Since each line is terminated by a new line, the last string + // is an empty string, which we don't want to send to the IPC + // server, so we take the last element of every element but the last. + const object = _.last(_.initial(_.split(data.toString(), /\r?\n/))); + ipc.of[process.env.IPC_SERVER_ID].emit('message', object); + }; child.stdout.on('data', emitMessage);