Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions github-code-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -465,15 +465,22 @@ async function searchAction(
// Race against a 2 s timeout so slow networks never delay the exit.
// Fix: use AbortController so the in-flight fetch is actually cancelled on timeout.
const updateAbortController = new AbortController();
// Fix: the losing Promise.race branch's timer is never cleared, and by default
// keeps the process alive until it fires — causing a ~2 s exit delay on every
// non-interactive run even when checkForUpdate resolves instantly. unref() lets
// the process exit as soon as the real work is done; clearTimeout on the winning
// path avoids a stray abort() firing after we've already moved on.
let updateCheckTimer!: ReturnType<typeof setTimeout>;
const latestTag = await Promise.race([
checkForUpdate(VERSION, GITHUB_TOKEN, updateAbortController.signal),
new Promise<null>((res) =>
setTimeout(() => {
new Promise<null>((res) => {
updateCheckTimer = setTimeout(() => {
updateAbortController.abort();
res(null);
}, 2000),
),
}, 2000).unref();
}),
]).catch(() => null);
clearTimeout(updateCheckTimer);
if (latestTag) {
const w = 55;
// Fix: compute all widths from totalWidth so corners always align.
Expand Down
6 changes: 6 additions & 0 deletions src/tui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ export async function runInteractive(
if (statsDebounceTimer !== null) clearTimeout(statsDebounceTimer);
process.stdin.setRawMode(false);
process.off("SIGWINCH", onResize);
// Unref stdin so the pending `for await` read can't keep the event loop
// alive while breaking out of the loop awaits the stream's teardown.
process.stdin.unref();
// Set flag to break out of the event loop and allow stdout buffer to flush
// before process termination. process.exit() may terminate too early.
shouldExit = true;
Expand Down Expand Up @@ -659,6 +662,9 @@ export async function runInteractive(
process.stdout.write(ANSI_CLEAR);
process.stdin.setRawMode(false);
process.off("SIGWINCH", onResize);
// Unref stdin so the pending `for await` read can't keep the event loop
// alive while breaking out of the loop awaits the stream's teardown.
process.stdin.unref();
if (statsDebounceTimer !== null) clearTimeout(statsDebounceTimer);
console.log(
buildOutput(groups, query, org, excludedRepos, excludedExtractRefs, format, outputType, {
Expand Down
Loading