mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-05 07:54:38 +00:00
fix(terminal): start the daemon when the terminal worker cannot start (#8810)
On 0.15.0 the daemon launches the detached terminal worker while it is being created, and the worker refuses to start unless it can read its own birth time and command line (Windows PowerShell 5.1 `Get-CimInstance`, `ps` elsewhere). Any failure of that query used to escape startWorkerTerminalManager and take the whole daemon down with "Daemon failed to start (exit 1)", as two Windows machines hit after the update: one whose PowerShell 5.1 cannot load CimCmdlets, one where powershell.exe cannot be spawned at all. 0.14.0 never ran that query at startup. The launch error is now logged and the daemon starts without a current worker. The pool already launches one lazily on the first terminal creation, so that request reports the same error while the machine still cannot run the query, and terminals come back once it can. The identity requirement itself is unchanged: a worker without a verified identity is never written or adopted.
This commit is contained in:
@@ -70,7 +70,7 @@ import {
|
||||
TerminalWorkerIncompatibleError,
|
||||
} from "./terminal-worker-pool.js";
|
||||
import { connectTerminalWorker } from "./terminal-worker-client.js";
|
||||
import { launchTerminalWorker } from "./terminal-worker-launch.js";
|
||||
import { launchTerminalWorker, TerminalWorkerLaunchError } from "./terminal-worker-launch.js";
|
||||
|
||||
type TerminalRow = TerminalState["grid"][number];
|
||||
|
||||
@@ -2671,3 +2671,34 @@ it.each([false, true])(
|
||||
},
|
||||
45000,
|
||||
);
|
||||
|
||||
// Both Windows reports in #8766: the worker's process identity query (PowerShell there, `ps` here)
|
||||
// fails, the worker exits before writing its record, and the daemon used to exit with it.
|
||||
it.skipIf(isPlatform("win32"))(
|
||||
"starts without a worker when the worker cannot read its own identity, and launches one once it can",
|
||||
async () => {
|
||||
const paseoHome = createTemporaryHome();
|
||||
const binDir = mkdtempSync(join(tmpdir(), "worker-terminal-manager-no-ps-"));
|
||||
temporaryDirs.push(binDir);
|
||||
writeFileSync(join(binDir, "ps"), "#!/bin/sh\nexit 1\n", { mode: 0o755 });
|
||||
const originalPath = process.env.PATH;
|
||||
process.env.PATH = `${binDir}${delimiter}${originalPath ?? ""}`;
|
||||
try {
|
||||
manager = await startRealWorkerManager({ paseoHome });
|
||||
expect(await workerRecords(paseoHome)).toEqual([]);
|
||||
await expect(
|
||||
manager.createTerminal({ workspaceId: "ws-no-identity", cwd: paseoHome }),
|
||||
).rejects.toThrow(TerminalWorkerLaunchError);
|
||||
expect(await workerRecords(paseoHome)).toEqual([]);
|
||||
} finally {
|
||||
process.env.PATH = originalPath;
|
||||
}
|
||||
|
||||
const terminal = trackTerminal(
|
||||
await manager.createTerminal({ workspaceId: "ws-no-identity", cwd: paseoHome }),
|
||||
);
|
||||
expect(terminal.id).toBeTruthy();
|
||||
expect((await workerRecords(paseoHome)).map((record) => record.pid)).toHaveLength(1);
|
||||
},
|
||||
30000,
|
||||
);
|
||||
|
||||
@@ -1269,8 +1269,17 @@ export async function startWorkerTerminalManager(
|
||||
try {
|
||||
current = await startCurrent();
|
||||
} catch (error) {
|
||||
if (!(error instanceof NoTerminalWorkerAvailableError)) throw error;
|
||||
logger.warn(error.message);
|
||||
if (error instanceof NoTerminalWorkerAvailableError) {
|
||||
logger.warn(error.message);
|
||||
} else {
|
||||
// The daemon starts without terminals rather than not at all. A worker that cannot start
|
||||
// here (its process identity query failed, say) is launched again by the first terminal
|
||||
// creation, which reports the same error if it still cannot.
|
||||
logger.error(
|
||||
{ err: error },
|
||||
"Terminal worker did not start; terminals are unavailable until one starts",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user