mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(cli): renders on Windows stop cancelling when an old parent's pid is reused (#5358)
* fix(cli): renders on Windows stop cancelling when an old parent's pid is reused * test(cli): a Windows parent created in the same tick as its child stays an ancestor
This commit is contained in:
@@ -85,8 +85,14 @@ export interface ProcessAncestor {
|
||||
|
||||
interface ProcessRecord extends ProcessAncestor {
|
||||
parentPid: number;
|
||||
startedAt?: bigint | undefined;
|
||||
}
|
||||
|
||||
const holdsReusedPid = (parent: ProcessRecord, child: ProcessRecord | undefined): boolean =>
|
||||
parent.startedAt !== undefined &&
|
||||
child?.startedAt !== undefined &&
|
||||
parent.startedAt > child.startedAt;
|
||||
|
||||
function recordsToAncestors(pid: number, records: readonly ProcessRecord[]): ProcessAncestor[] {
|
||||
const byPid = new Map(records.map((record) => [record.pid, record]));
|
||||
const ancestors: ProcessAncestor[] = [];
|
||||
@@ -94,11 +100,12 @@ function recordsToAncestors(pid: number, records: readonly ProcessRecord[]): Pro
|
||||
let current = pid;
|
||||
|
||||
for (let depth = 0; depth < 64; depth++) {
|
||||
const parent = byPid.get(current)?.parentPid;
|
||||
const child = byPid.get(current);
|
||||
const parent = child?.parentPid;
|
||||
if (parent === undefined || parent <= 1 || visited.has(parent)) break;
|
||||
visited.add(parent);
|
||||
const ancestor = byPid.get(parent);
|
||||
if (!ancestor) break;
|
||||
if (!ancestor || holdsReusedPid(ancestor, child)) break;
|
||||
ancestors.push({ pid: ancestor.pid, identity: ancestor.identity });
|
||||
current = parent;
|
||||
}
|
||||
@@ -128,13 +135,17 @@ export function processAncestorSnapshot(pid: number): ProcessAncestor[] {
|
||||
const records = output
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim().split(/\s+/))
|
||||
.map(([processId, parentProcessId, creationDate]) => ({
|
||||
pid: Number(processId),
|
||||
parentPid: Number(parentProcessId),
|
||||
identity: creationDate ? `windows:${creationDate}` : "",
|
||||
}))
|
||||
.map(
|
||||
([processId, parentProcessId, creationDate]): ProcessRecord => ({
|
||||
pid: Number(processId),
|
||||
parentPid: Number(parentProcessId),
|
||||
identity: creationDate ? `windows:${creationDate}` : "",
|
||||
startedAt:
|
||||
creationDate && /^\d+$/.test(creationDate) ? BigInt(creationDate) : undefined,
|
||||
}),
|
||||
)
|
||||
.filter(
|
||||
(record): record is ProcessRecord =>
|
||||
(record) =>
|
||||
Number.isInteger(record.pid) &&
|
||||
record.pid > 0 &&
|
||||
Number.isInteger(record.parentPid) &&
|
||||
|
||||
@@ -57,4 +57,19 @@ describe("Windows orphan-cleanup child-process options", () => {
|
||||
expect.objectContaining({ windowsHide: true }),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps a Windows parent created in the same tick as its child", () => {
|
||||
execFileSyncMock.mockImplementation(() => "400 300 333\n300 200 333\n200 1 222\n");
|
||||
|
||||
expect(processAncestorSnapshot(400).map((ancestor) => ancestor.pid)).toEqual([300, 200]);
|
||||
});
|
||||
|
||||
it("stops the Windows ancestor chain at a parent pid reused by a later process", () => {
|
||||
execFileSyncMock.mockImplementation(() => "400 300 444\n300 200 333\n200 999 222\n999 5 555\n");
|
||||
|
||||
expect(processAncestorSnapshot(400)).toEqual([
|
||||
{ pid: 300, identity: "windows:333" },
|
||||
{ pid: 200, identity: "windows:222" },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user