mirror of
https://github.com/morluto/rea.git
synced 2026-10-31 20:06:14 +00:00
fix(process): preserve partial evidence and verify detached cleanup (#1011)
* test(ci): allow transport delivery in source identity regression * fix(process): preserve partial evidence and verify detached cleanup * fix(process): scope Linux token sweeps by stable process identity * fix(process): retain environment permission failure codes * fix(process): wait for signaled processes before verifying cleanup * fix(process): verify sampled detached groups during cleanup * fix(electron): preserve prelaunch identities through cleanup * fix(process): retry growing Darwin process table snapshots * fix(process): retain compatibility with saved v3 capture evidence * fix(process): migrate saved v3 captures during reconstruction verification * fix(process): preserve cancellation during Darwin helper compilation * fix(process): propagate cancellation through ownership baselines * perf(javascript): cache canonical export comparison sort keys * fix(process): cancel provider ownership preparation before spawn * fix(process): isolate native compiler waiter cancellation
This commit is contained in:
1 parent
63ba7424c0
commit
63cf28fd8f
51 files changed
+5506
-316
No files matched your search
@@ -64,6 +64,177 @@ describe("owned process-group cleanup discovery", () => {
|
||||
});
|
||||
expect(signalGroup).toHaveBeenCalledWith(100, "SIGKILL");
|
||||
});
|
||||
});
|
||||
|
||||
describe("opaque process neighbors during cleanup", () => {
|
||||
it("cleans verified run-owned groups while reporting an opaque neighbor", async () => {
|
||||
const processes = [
|
||||
{ pid: 100, parentPid: 1, processGroupId: 100, command: "capture" },
|
||||
{
|
||||
pid: 200,
|
||||
parentPid: 1,
|
||||
processGroupId: 200,
|
||||
command: "detached-child",
|
||||
},
|
||||
{
|
||||
pid: 900,
|
||||
parentPid: 1,
|
||||
processGroupId: 900,
|
||||
command: "opaque-neighbor",
|
||||
},
|
||||
].map((process) => ({ ...process, state: "S" }));
|
||||
const signalGroup = vi.fn();
|
||||
const identities = new Map(
|
||||
processes.map(({ pid }) => [
|
||||
pid,
|
||||
{ state: "readable" as const, identity: `start-${String(pid)}` },
|
||||
]),
|
||||
);
|
||||
const adapter: ProcessOwnershipHost = {
|
||||
listProcesses: () => Promise.resolve(processes),
|
||||
environment: (pid) =>
|
||||
Promise.resolve({
|
||||
REA_PROCESS_RUN_ID: pid === 900 ? "unowned" : "run-token",
|
||||
}),
|
||||
processIdentities: () => Promise.resolve(identities),
|
||||
runTokens: (members) =>
|
||||
Promise.resolve(
|
||||
new Map(
|
||||
members.map(({ pid }) => [
|
||||
pid,
|
||||
pid === 900
|
||||
? {
|
||||
state: "unavailable" as const,
|
||||
reason: "environment_unavailable",
|
||||
}
|
||||
: { state: "readable" as const, runId: "run-token" },
|
||||
]),
|
||||
),
|
||||
),
|
||||
signalGroup,
|
||||
};
|
||||
|
||||
const result = await cleanupOwnedProcessGroup(
|
||||
{
|
||||
...ownership,
|
||||
sweepTokenOwnedProcesses: true,
|
||||
captureBaseline: [],
|
||||
},
|
||||
adapter,
|
||||
);
|
||||
|
||||
expect(result).toMatchObject({
|
||||
cleaned: false,
|
||||
reason: expect.stringContaining("environment_unavailable=1"),
|
||||
});
|
||||
expect(signalGroup.mock.calls).toEqual([
|
||||
[100, "SIGKILL"],
|
||||
[200, "SIGKILL"],
|
||||
]);
|
||||
expect(signalGroup).not.toHaveBeenCalledWith(900, "SIGKILL");
|
||||
});
|
||||
});
|
||||
|
||||
describe("sampled detached process groups during cleanup", () => {
|
||||
it("signals only token-authenticated sampled groups and reports an unowned sample", async () => {
|
||||
const processes = [
|
||||
{
|
||||
pid: 100,
|
||||
parentPid: 1,
|
||||
processGroupId: 100,
|
||||
state: "S",
|
||||
command: "capture",
|
||||
},
|
||||
{
|
||||
pid: 200,
|
||||
parentPid: 1,
|
||||
processGroupId: 200,
|
||||
state: "S",
|
||||
command: "sanitized-detached-child",
|
||||
},
|
||||
];
|
||||
const signalGroup = vi.fn();
|
||||
const identities = new Map([
|
||||
[100, { state: "readable" as const, identity: "start-100" }],
|
||||
[200, { state: "readable" as const, identity: "start-200" }],
|
||||
]);
|
||||
const adapter: ProcessOwnershipHost = {
|
||||
listProcesses: () => Promise.resolve(processes),
|
||||
environment: (pid) =>
|
||||
Promise.resolve(pid === 100 ? { REA_PROCESS_RUN_ID: "run-token" } : {}),
|
||||
processIdentities: () => Promise.resolve(identities),
|
||||
runTokens: (members) =>
|
||||
Promise.resolve(
|
||||
new Map(
|
||||
members.map(({ pid }) => [
|
||||
pid,
|
||||
{
|
||||
state: "readable" as const,
|
||||
runId: pid === 100 ? "run-token" : undefined,
|
||||
},
|
||||
]),
|
||||
),
|
||||
),
|
||||
signalGroup,
|
||||
};
|
||||
|
||||
const result = await cleanupOwnedProcessGroup(
|
||||
{
|
||||
...ownership,
|
||||
sweepTokenOwnedProcesses: true,
|
||||
sampledProcessGroupIds: [200],
|
||||
},
|
||||
adapter,
|
||||
);
|
||||
|
||||
expect(result).toMatchObject({
|
||||
cleaned: false,
|
||||
reason: "process tree contains an unowned or PID-reused process",
|
||||
failures: [{ pid: 200, reason: "run-token-mismatch" }],
|
||||
});
|
||||
expect(signalGroup).toHaveBeenCalledTimes(1);
|
||||
expect(signalGroup).toHaveBeenCalledWith(100, "SIGKILL");
|
||||
expect(signalGroup).not.toHaveBeenCalledWith(200, "SIGKILL");
|
||||
});
|
||||
|
||||
it("reports a live sampled group after the launcher has exited without signaling it", async () => {
|
||||
const process = {
|
||||
pid: 200,
|
||||
parentPid: 1,
|
||||
processGroupId: 200,
|
||||
state: "S",
|
||||
command: "sanitized-detached-child",
|
||||
};
|
||||
const signalGroup = vi.fn();
|
||||
const adapter: ProcessOwnershipHost = {
|
||||
listProcesses: () => Promise.resolve([process]),
|
||||
environment: () => Promise.resolve({}),
|
||||
runTokens: () =>
|
||||
Promise.resolve(
|
||||
new Map([[200, { state: "readable" as const, runId: undefined }]]),
|
||||
),
|
||||
signalGroup,
|
||||
};
|
||||
|
||||
const result = await cleanupOwnedProcessGroup(
|
||||
{
|
||||
...ownership,
|
||||
sweepTokenOwnedProcesses: true,
|
||||
sampledProcessGroupIds: [200],
|
||||
},
|
||||
adapter,
|
||||
);
|
||||
|
||||
expect(result).toMatchObject({
|
||||
cleaned: false,
|
||||
reason: "process tree contains an unowned or PID-reused process",
|
||||
failures: [{ pid: 200, reason: "run-token-mismatch" }],
|
||||
});
|
||||
expect(signalGroup).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("rooted process-group cleanup", () => {
|
||||
it("validates and signals rooted descendant groups once, root first", async () => {
|
||||
const processes = [
|
||||
{ pid: 100, parentPid: 1, processGroupId: 100 },
|
||||
|
||||
Reference in new issue
Block a user