Simplify stderr buffers and EOL splitting

Co-authored-by: Robert <robertbrignull@github.com>
This commit is contained in:
Koen Vlaswinkel
2024-02-19 16:40:27 +01:00
parent 5ddc3c11d3
commit 1b66767d43

View File

@@ -362,8 +362,8 @@ export class CodeQLCliServer implements Disposable {
silent?: boolean, silent?: boolean,
): Promise<string> { ): Promise<string> {
const stderrBuffers: Buffer[] = []; const stderrBuffers: Buffer[] = [];
// The array of fragments of stderr of this line. To be used for logging. // The current buffer of stderr of a single line. To be used for logging.
let currentLineStderrBuffers: Buffer[] = []; let currentLineStderrBuffer: Buffer = Buffer.alloc(0);
if (this.commandInProcess) { if (this.commandInProcess) {
throw new Error("runCodeQlCliInternal called while cli was running"); throw new Error("runCodeQlCliInternal called while cli was running");
} }
@@ -423,28 +423,34 @@ export class CodeQLCliServer implements Disposable {
stderrBuffers.push(newData); stderrBuffers.push(newData);
if (!silent) { if (!silent) {
currentLineStderrBuffers.push(newData); currentLineStderrBuffer = Buffer.concat([
currentLineStderrBuffer,
newData,
]);
// Print the stderr to the logger as it comes in. We need to ensure that // Print the stderr to the logger as it comes in. We need to ensure that
// we don't split messages on the same line, so we buffer the stderr and // we don't split messages on the same line, so we buffer the stderr and
// split it on EOLs. // split it on EOLs.
let currentLineBuffer = Buffer.concat(currentLineStderrBuffers);
const eolBuffer = Buffer.from(EOL); const eolBuffer = Buffer.from(EOL);
if (currentLineBuffer.includes(eolBuffer)) {
while (currentLineBuffer.includes(eolBuffer)) {
const line = currentLineBuffer.subarray(
0,
currentLineBuffer.indexOf(eolBuffer),
);
void this.logger.log(line.toString("utf-8")); let hasCreatedSubarray = false;
currentLineBuffer = currentLineBuffer.subarray( let eolIndex;
currentLineBuffer.indexOf(eolBuffer) + eolBuffer.length, while (
); (eolIndex = currentLineStderrBuffer.indexOf(eolBuffer)) !== -1
} ) {
const line = currentLineStderrBuffer.subarray(0, eolIndex);
void this.logger.log(line.toString("utf-8"));
currentLineStderrBuffer = currentLineStderrBuffer.subarray(
eolIndex + eolBuffer.length,
);
hasCreatedSubarray = true;
}
currentLineStderrBuffers = [currentLineBuffer]; // We have created a subarray, which means that the complete original buffer is now referenced
// by the subarray. We need to create a new buffer to avoid memory leaks.
if (hasCreatedSubarray) {
currentLineStderrBuffer = Buffer.from(currentLineStderrBuffer);
} }
} }
}); });
@@ -461,10 +467,8 @@ export class CodeQLCliServer implements Disposable {
// Make sure we remove the terminator; // Make sure we remove the terminator;
const data = fullBuffer.toString("utf8", 0, fullBuffer.length - 1); const data = fullBuffer.toString("utf8", 0, fullBuffer.length - 1);
if (!silent) { if (!silent) {
void this.logger.log( void this.logger.log(currentLineStderrBuffer.toString("utf8"));
Buffer.concat(currentLineStderrBuffers).toString("utf8"), currentLineStderrBuffer = Buffer.alloc(0);
);
currentLineStderrBuffers = [];
void this.logger.log("CLI command succeeded."); void this.logger.log("CLI command succeeded.");
} }
return data; return data;
@@ -484,10 +488,8 @@ export class CodeQLCliServer implements Disposable {
cliError.stack += getErrorStack(err); cliError.stack += getErrorStack(err);
throw cliError; throw cliError;
} finally { } finally {
if (!silent && currentLineStderrBuffers.length > 0) { if (!silent && currentLineStderrBuffer.length > 0) {
void this.logger.log( void this.logger.log(currentLineStderrBuffer.toString("utf8"));
Buffer.concat(currentLineStderrBuffers).toString("utf8"),
);
} }
// Remove the listeners we set up. // Remove the listeners we set up.
process.stdout.removeAllListeners("data"); process.stdout.removeAllListeners("data");