fix(cli): render starts in a sandbox that forbids lowering CPU priority (#5814)

This commit is contained in:
Miguel Ángel
2026-10-17 21:34:56 +00:00
committed by GitHub
parent d0da232ec9
commit 7e00f37be2
2 changed files with 30 additions and 4 deletions
@@ -1,5 +1,5 @@
import { constants } from "node:os";
import { afterEach, expect, it, vi } from "vitest";
import { afterEach, beforeEach, expect, it, vi } from "vitest";
const os = vi.hoisted(() => ({ setPriority: vi.fn() }));
vi.mock("node:os", async (importOriginal) => ({
@@ -8,11 +8,15 @@ vi.mock("node:os", async (importOriginal) => ({
}));
vi.mock("./utils/lintProject.js", () => ({ lintProject: vi.fn(async () => ({ ok: true })) }));
beforeEach(() => {
vi.resetModules();
os.setPriority.mockReset();
process.argv[2] = "lint";
process.env.HYPERFRAMES_RENDER_SETUP_INPUT = JSON.stringify({ projectDir: "/project" });
});
afterEach(() => vi.restoreAllMocks());
it("lints at the lowest CPU priority so it never competes with a Studio boot", async () => {
process.argv[2] = "lint";
process.env.HYPERFRAMES_RENDER_SETUP_INPUT = JSON.stringify({ projectDir: "/project" });
const write = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
await import("./renderSetupWorker.js");
@@ -20,3 +24,17 @@ it("lints at the lowest CPU priority so it never competes with a Studio boot", a
expect(os.setPriority).toHaveBeenCalledWith(constants.priority.PRIORITY_LOW);
expect(write).toHaveBeenCalledWith(expect.stringContaining('{"ok":true}'));
});
it("still lints when a sandbox forbids lowering the priority", async () => {
os.setPriority.mockImplementation(() => {
throw new Error("uv_os_setpriority returned EPERM (operation not permitted)");
});
const write = vi.spyOn(process.stdout, "write").mockImplementation(() => true);
const warn = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
await import("./renderSetupWorker.js");
expect(write).toHaveBeenCalledWith(expect.stringContaining('{"ok":true}'));
expect(warn).toHaveBeenCalledTimes(1);
expect(warn).toHaveBeenCalledWith(expect.stringContaining("EPERM"));
});
+9 -1
View File
@@ -18,11 +18,19 @@ const disposeSignalHandlers = installRenderSetupSignalHandlers(
process.env.HYPERFRAMES_RENDER_DETACHED !== "1",
);
function lowerPriority(): void {
try {
setPriority(constants.priority.PRIORITY_LOW);
} catch (error) {
process.stderr.write(`Lint runs at normal priority: ${(error as Error).message}\n`);
}
}
async function runMode(): Promise<unknown> {
if (mode === "browser") return ensureBrowser(input);
if (mode === "lint") {
// Nobody waits on a background lint the way they wait on a Studio boot, so it takes idle CPU only.
setPriority(constants.priority.PRIORITY_LOW);
lowerPriority();
return lintProject(
input.projectDir,
input.entryFile,