diff --git a/apps/electron-backend/src/app/startup/login-shell-path.spec.ts b/apps/electron-backend/src/app/startup/login-shell-path.spec.ts index 9d5e2970e..ea0d74148 100644 --- a/apps/electron-backend/src/app/startup/login-shell-path.spec.ts +++ b/apps/electron-backend/src/app/startup/login-shell-path.spec.ts @@ -84,6 +84,11 @@ describe('login shell PATH', () => { const stuck = loadModule(); stuck.scheduleDeferredFixPath(() => new Promise(() => undefined)); await expect(stuck.waitForLoginShellPath(5)).resolves.toBeUndefined(); + // Later spawns do not wait out the limit again (the test would time + // out on this one otherwise). + await expect( + stuck.waitForLoginShellPath(60_000) + ).resolves.toBeUndefined(); }); it('lets spawns go immediately on Windows', async () => { diff --git a/apps/electron-backend/src/app/startup/login-shell-path.ts b/apps/electron-backend/src/app/startup/login-shell-path.ts index c35fea1bf..bd63070e3 100644 --- a/apps/electron-backend/src/app/startup/login-shell-path.ts +++ b/apps/electron-backend/src/app/startup/login-shell-path.ts @@ -32,17 +32,27 @@ const loginShellPathSettled: Promise = /** Upper bound for a waiting spawn when the login shell never returns. */ export const LOGIN_SHELL_PATH_WAIT_LIMIT_MS = 10_000; +// Set once a wait has run out: a shell that hung that long is not waited +// for again, so one broken profile delays one launch, not every launch. +let loginShellPathWaitExpired = false; /** * Resolves once the login shell PATH lookup has finished (successfully or - * not), at the latest after `limitMs`; immediately on Windows. + * not), at the latest after `limitMs`; immediately on Windows and after a + * previous wait has run out. */ export function waitForLoginShellPath( limitMs = LOGIN_SHELL_PATH_WAIT_LIMIT_MS ): Promise { + if (loginShellPathWaitExpired) { + return Promise.resolve(); + } let timer: NodeJS.Timeout | undefined; const limit = new Promise((resolve) => { - timer = setTimeout(resolve, limitMs); + timer = setTimeout(() => { + loginShellPathWaitExpired = true; + resolve(); + }, limitMs); }); return Promise.race([loginShellPathSettled, limit]).finally(() => clearTimeout(timer)