Skip to content

Commit bb7e563

Browse files
cklinCopilot
andcommitted
diag: instrument CLI server stdin writes for EPIPE origin
Query-server diagnostics showed no query-server exit/error and no sendRequest failure, so the EPIPE is not the query server. codeQL. restartQueryServer also restarts the CLI server (cliServer.restartCliServer), so instrument the CLI server: log restart/kill boundaries, launched pids, and attach a stdin 'error' listener + guard around the command write to capture the exact write site and restart interleaving. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 90105d62-02ab-405e-9c95-10466c971814
1 parent 39e7a5e commit bb7e563

1 file changed

Lines changed: 38 additions & 3 deletions

File tree

  • extensions/ql-vscode/src/codeql-cli

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,10 @@ export class CodeQLCliServer implements Disposable {
313313

314314
killProcessIfRunning(): void {
315315
if (this.process) {
316+
// DIAG-EPIPE: CLI server teardown boundary.
317+
console.error(
318+
`DIAG-CLI killProcessIfRunning pid=${this.process.pid} commandInProcess=${this.commandInProcess} at=${new Date().toISOString()}`,
319+
);
316320
// Tell the Java CLI server process to shut down.
317321
void this.logger.log("Sending shutdown request");
318322
try {
@@ -353,8 +357,16 @@ export class CodeQLCliServer implements Disposable {
353357
// If the server is not running a command run this immediately
354358
// otherwise add to the front of the queue (as we want to run this after the next command()).
355359
if (this.commandInProcess) {
360+
// DIAG-EPIPE: restart deferred behind an in-flight command.
361+
console.error(
362+
`DIAG-CLI restartCliServer deferred (commandInProcess) at=${new Date().toISOString()}`,
363+
);
356364
this.commandQueue.unshift(callback);
357365
} else {
366+
// DIAG-EPIPE: restart executed immediately.
367+
console.error(
368+
`DIAG-CLI restartCliServer immediate at=${new Date().toISOString()}`,
369+
);
358370
callback();
359371
}
360372
}
@@ -382,7 +394,7 @@ export class CodeQLCliServer implements Disposable {
382394
]
383395
: [];
384396

385-
return spawnServer(
397+
const child = spawnServer(
386398
codeQlPath,
387399
"CodeQL CLI Server",
388400
["execute", "cli-server"],
@@ -392,6 +404,11 @@ export class CodeQLCliServer implements Disposable {
392404
/**/
393405
},
394406
);
407+
// DIAG-EPIPE: record CLI server pid to correlate with stdin errors.
408+
console.error(
409+
`DIAG-CLI launched CLI server pid=${child.pid} at=${new Date().toISOString()}`,
410+
);
411+
return child;
395412
}
396413

397414
private async runCodeQlCliInternal(
@@ -422,9 +439,27 @@ export class CodeQLCliServer implements Disposable {
422439
return await this.handleProcessOutput(this.process, {
423440
handleNullTerminator: true,
424441
onListenStart: (process) => {
442+
// DIAG-EPIPE: capture the async EPIPE (emitted on stdin) with a
443+
// stack, and the pid we are writing to, to confirm the CLI server
444+
// is the source and observe the restart interleaving.
445+
process.stdin.on("error", (e: Error) => {
446+
console.error(
447+
`DIAG-CLI stdin 'error' pid=${process.pid} isCurrent=${this.process === process} ` +
448+
`commandInProcess=${this.commandInProcess} err=${e.name}:${e.message} at=${new Date().toISOString()}\n` +
449+
`${e.stack}`,
450+
);
451+
});
425452
// Write the command followed by a null terminator.
426-
process.stdin.write(JSON.stringify(args), "utf8");
427-
process.stdin.write(this.nullBuffer);
453+
try {
454+
process.stdin.write(JSON.stringify(args), "utf8");
455+
process.stdin.write(this.nullBuffer);
456+
} catch (e) {
457+
console.error(
458+
`DIAG-CLI stdin write threw pid=${process.pid} isCurrent=${this.process === process} ` +
459+
`err=${e instanceof Error ? `${e.name}:${e.message}` : String(e)} at=${new Date().toISOString()}`,
460+
);
461+
throw e;
462+
}
428463
},
429464
description,
430465
args,

0 commit comments

Comments
 (0)