Skip to content

Commit b458ca3

Browse files
authored
Wait for stdout writing to finish before exiting (#262)
This fixes a race condition when writing to stdout on certain platforms and streams. As noted in [A note on process I/O](https://nodejs.org/api/process.html#process_a_note_on_process_i_o) in the Node documentation, the `process.stdout` stream is asynchronous in some cases (pipes on POSIX, TTYs on Windows). In these cases, the output sent to stdout can sometimes be cut off at the first chunk because the linter process exits before the stream is finished writing. The result is either a truncated set of errors (with default output) or invalid JSON (with JSON output) when the set of errors exceeds the default chunk size. This is fixed by using the return status of `socket.write` to determine if some of the data was queued, then awaiting the socket's `'drain'` event if so before returning.
1 parent cf942a2 commit b458ca3

File tree

2 files changed

+14
-1
lines changed

2 files changed

+14
-1
lines changed

src/runner.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,12 @@ export async function run(stdout, stdin, stderr, argv) {
111111
const errors = validateSchemaDefinition(schema, rules, configuration);
112112
const groupedErrors = groupErrorsBySchemaFilePath(errors, schema.sourceMap);
113113

114-
stdout.write(formatter(groupedErrors));
114+
const writeResult = stdout.write(formatter(groupedErrors));
115+
if (!writeResult) {
116+
await new Promise((resolve) => {
117+
stdout.on('drain', () => resolve());
118+
});
119+
}
115120

116121
return errors.length > 0 ? 1 : 0;
117122
}

test/runner.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,21 @@ describe('Runner', () => {
1010
write: (text) => {
1111
stdout = stdout + text;
1212
},
13+
on: (_eventName, callback) => {
14+
const delay = Math.random() * (20 - 10) + 10;
15+
setTimeout(callback, delay);
16+
},
1317
};
1418

1519
var stderr;
1620
var mockStderr = {
1721
write: (text) => {
1822
stderr = stderr + text;
1923
},
24+
on: (_eventName, callback) => {
25+
const delay = Math.random() * (20 - 10) + 10;
26+
setTimeout(callback, delay);
27+
},
2028
};
2129

2230
beforeEach(() => {

0 commit comments

Comments
 (0)