@@ -362,6 +362,8 @@ export class CodeQLCliServer implements Disposable {
362
362
silent ?: boolean ,
363
363
) : Promise < string > {
364
364
const stderrBuffers : Buffer [ ] = [ ] ;
365
+ // The current buffer of stderr of a single line. To be used for logging.
366
+ let currentLineStderrBuffer : Buffer = Buffer . alloc ( 0 ) ;
365
367
if ( this . commandInProcess ) {
366
368
throw new Error ( "runCodeQlCliInternal called while cli was running" ) ;
367
369
}
@@ -419,6 +421,38 @@ export class CodeQLCliServer implements Disposable {
419
421
// Listen to stderr
420
422
process . stderr . addListener ( "data" , ( newData : Buffer ) => {
421
423
stderrBuffers . push ( newData ) ;
424
+
425
+ if ( ! silent ) {
426
+ currentLineStderrBuffer = Buffer . concat ( [
427
+ currentLineStderrBuffer ,
428
+ newData ,
429
+ ] ) ;
430
+
431
+ // Print the stderr to the logger as it comes in. We need to ensure that
432
+ // we don't split messages on the same line, so we buffer the stderr and
433
+ // split it on EOLs.
434
+ const eolBuffer = Buffer . from ( EOL ) ;
435
+
436
+ let hasCreatedSubarray = false ;
437
+
438
+ let eolIndex ;
439
+ while (
440
+ ( eolIndex = currentLineStderrBuffer . indexOf ( eolBuffer ) ) !== - 1
441
+ ) {
442
+ const line = currentLineStderrBuffer . subarray ( 0 , eolIndex ) ;
443
+ void this . logger . log ( line . toString ( "utf-8" ) ) ;
444
+ currentLineStderrBuffer = currentLineStderrBuffer . subarray (
445
+ eolIndex + eolBuffer . length ,
446
+ ) ;
447
+ hasCreatedSubarray = true ;
448
+ }
449
+
450
+ // We have created a subarray, which means that the complete original buffer is now referenced
451
+ // by the subarray. We need to create a new buffer to avoid memory leaks.
452
+ if ( hasCreatedSubarray ) {
453
+ currentLineStderrBuffer = Buffer . from ( currentLineStderrBuffer ) ;
454
+ }
455
+ }
422
456
} ) ;
423
457
// Listen for process exit.
424
458
process . addListener ( "close" , ( code ) =>
@@ -433,6 +467,8 @@ export class CodeQLCliServer implements Disposable {
433
467
// Make sure we remove the terminator;
434
468
const data = fullBuffer . toString ( "utf8" , 0 , fullBuffer . length - 1 ) ;
435
469
if ( ! silent ) {
470
+ void this . logger . log ( currentLineStderrBuffer . toString ( "utf8" ) ) ;
471
+ currentLineStderrBuffer = Buffer . alloc ( 0 ) ;
436
472
void this . logger . log ( "CLI command succeeded." ) ;
437
473
}
438
474
return data ;
@@ -452,8 +488,8 @@ export class CodeQLCliServer implements Disposable {
452
488
cliError . stack += getErrorStack ( err ) ;
453
489
throw cliError ;
454
490
} finally {
455
- if ( ! silent ) {
456
- void this . logger . log ( Buffer . concat ( stderrBuffers ) . toString ( "utf8" ) ) ;
491
+ if ( ! silent && currentLineStderrBuffer . length > 0 ) {
492
+ void this . logger . log ( currentLineStderrBuffer . toString ( "utf8" ) ) ;
457
493
}
458
494
// Remove the listeners we set up.
459
495
process . stdout . removeAllListeners ( "data" ) ;
0 commit comments