fix(CLI): wait for robot output to be flushed before exitting (#616)

When using the `--robot` option, we write to `stdout`/`stderr` using
`WritableStream#write()`. This operation is asynchronous, however we're
not waiting for the data to be flushed before calling `process.exit()`
right after emitting the `done` event.

This causes a rance condition where sometimes `done` is never written to
the log file, and therefore the GUI remains waiting forever.

Change-Type: patch
Changelog-Entry: Fix application stuck at "Finishing".
See: https://github.com/resin-io/etcher/issues/613
See: https://github.com/resin-io/etcher/issues/609
See: https://github.com/resin-io/etcher/issues/573
Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
Juan Cruz Viotti 2016-08-02 21:52:39 -04:00 committed by GitHub
parent bdbff0e814
commit 49bb9677cd
2 changed files with 58 additions and 34 deletions

View File

@ -91,43 +91,48 @@ form.run([
});
}).then((results) => {
if (options.robot) {
log.toStdout(JSON.stringify({
command: 'done',
data: {
passedValidation: results.passedValidation,
sourceChecksum: results.sourceChecksum
}
}));
} else {
return Bluebird.try(() => {
if (options.robot) {
return log.toStdout(JSON.stringify({
command: 'done',
data: {
passedValidation: results.passedValidation,
sourceChecksum: results.sourceChecksum
}
}));
}
if (results.passedValidation) {
console.log('Your flash is complete!');
console.log(`Checksum: ${results.sourceChecksum}`);
} else {
console.error('Validation failed!');
}
}
if (results.passedValidation) {
process.exit(EXIT_CODES.SUCCESS);
} else {
process.exit(EXIT_CODES.VALIDATION_ERROR);
}
}).then(() => {
if (results.passedValidation) {
process.exit(EXIT_CODES.SUCCESS);
} else {
process.exit(EXIT_CODES.VALIDATION_ERROR);
}
});
}).catch((error) => {
if (options.robot) {
log.toStderr(JSON.stringify({
command: 'error',
data: {
message: error.message,
description: error.description,
code: error.code
}
}));
} else {
utils.printError(error);
}
return Bluebird.try(() => {
if (options.robot) {
return log.toStderr(JSON.stringify({
command: 'error',
data: {
message: error.message,
description: error.description,
code: error.code
}
}));
}
utils.printError(error);
}).then(() => {
process.exit(EXIT_CODES.GENERAL_ERROR);
});
process.exit(EXIT_CODES.GENERAL_ERROR);
}).finally(log.close);

View File

@ -16,6 +16,7 @@
'use strict';
const Bluebird = require('bluebird');
const fs = require('fs');
const options = require('./cli');
const logStream = options.log ? fs.createWriteStream(options.log) : null;
@ -46,12 +47,17 @@ const STDERR_STREAM = logStream || process.stderr;
* to it, otherwise to `process.stdout`.
*
* @param {String} line - line
* @returns {Promise}
*
* @example
* log.toStdout('Hello world!');
*/
exports.toStdout = (line) => {
STDOUT_STREAM.write(line + '\n');
return new Bluebird((resolve) => {
STDOUT_STREAM.write(line + '\n', () => {
return resolve();
});
});
};
/**
@ -64,12 +70,17 @@ exports.toStdout = (line) => {
* to it, otherwise to `process.stderr`.
*
* @param {String} line - line
* @returns {Promise}
*
* @example
* log.toStderr('Hello world!');
*/
exports.toStderr = (line) => {
STDERR_STREAM.write(line + '\n');
return new Bluebird((resolve) => {
STDERR_STREAM.write(line + '\n', () => {
return resolve();
});
});
};
/**
@ -77,11 +88,19 @@ exports.toStderr = (line) => {
* @function
* @public
*
* @returns {Promise}
*
* @example
* log.close();
*/
exports.close = () => {
if (logStream) {
logStream.close();
}
return new Bluebird((resolve) => {
if (!logStream) {
return resolve();
}
logStream.close(() => {
return resolve();
});
});
};