mirror of
https://github.com/morluto/rea.git
synced 2026-11-09 16:26:36 +00:00
fix(process): retain child scope and bound native exit waits (#5280)
Retain original parent/child scope and prior native-generation proof across exit settlement and token retries. Keep historical scope separate from signal authority, count each supplied snapshot once, and share one existing native-exit deadline throughout cleanup. Validated 387 affected tests (one Darwin-only skip), five controls repeated three times, and 30 synced-main integration tests (one platform skip). Synced-head static, architecture, docs and discovery checks pass; real GDB qualification passes 44 CLI/MCP cases. Native-observer edge controls are simulated. Assisted-by: Reimu (gensokyo-skills:reimu-incident-triage) Assisted-by: Kogasa (gensokyo-skills:kogasa-surprise-testing)
This commit is contained in:
1 parent
10f1994fe1
commit
71ae02c6ef
5 files changed
+293
-18
No files matched your search
@@ -6,6 +6,7 @@ import {
|
||||
processIdentityIsExiting,
|
||||
PROCESS_CLEANUP_VERIFICATION_GRACE_MS,
|
||||
PROCESS_CLEANUP_VERIFICATION_INTERVAL_MS,
|
||||
type ProcessExitSettlementBudget,
|
||||
} from "./ProcessLifecycle.js";
|
||||
import { parseLinuxProcessStat } from "./LinuxProcessStat.js";
|
||||
import { parseLinuxProcessEffectiveUid } from "./LinuxProcessStatus.js";
|
||||
@@ -539,6 +540,7 @@ export const settleExitingProcessIdentities = async (
|
||||
host: ProcessOwnershipHost,
|
||||
initial: ReadonlyMap<number, ProcessIdentityObservation>,
|
||||
signal?: AbortSignal,
|
||||
budget: ProcessExitSettlementBudget = { deadline: undefined },
|
||||
): Promise<ReadonlyMap<number, ProcessIdentityObservation>> => {
|
||||
signal?.throwIfAborted();
|
||||
let pending = processes.filter(({ pid }) =>
|
||||
@@ -546,7 +548,8 @@ export const settleExitingProcessIdentities = async (
|
||||
);
|
||||
if (pending.length === 0) return initial;
|
||||
const identities = new Map(initial);
|
||||
const deadline = performance.now() + PROCESS_CLEANUP_VERIFICATION_GRACE_MS;
|
||||
const deadline = (budget.deadline ??=
|
||||
performance.now() + PROCESS_CLEANUP_VERIFICATION_GRACE_MS);
|
||||
while (pending.length > 0) {
|
||||
const remaining = deadline - performance.now();
|
||||
if (remaining <= 0) break;
|
||||
@@ -589,6 +592,7 @@ export const readProcessOwnershipFacts = async (
|
||||
signal?: AbortSignal,
|
||||
options: {
|
||||
readonly identityBefore?: ReadonlyMap<number, ProcessIdentityObservation>;
|
||||
readonly exitSettlement?: ProcessExitSettlementBudget;
|
||||
} = {},
|
||||
): Promise<readonly ProcessOwnershipFact[]> => {
|
||||
signal?.throwIfAborted();
|
||||
@@ -627,19 +631,30 @@ export const readProcessOwnershipFacts = async (
|
||||
.filter(({ pid }) => tokens.get(pid)?.state !== "readable")
|
||||
.map(({ pid }) => pid),
|
||||
);
|
||||
const observedAfter = await readIdentityFacts(
|
||||
processes,
|
||||
host,
|
||||
"after",
|
||||
signal,
|
||||
effectiveUidPids,
|
||||
);
|
||||
const identityAfter = await settleExitingProcessIdentities(
|
||||
processes,
|
||||
host,
|
||||
await readIdentityFacts(processes, host, "after", signal, effectiveUidPids),
|
||||
observedAfter,
|
||||
signal,
|
||||
options.exitSettlement,
|
||||
);
|
||||
signal?.throwIfAborted();
|
||||
const facts = processes.map((process): ProcessOwnershipFact => {
|
||||
const deriveFact = (
|
||||
process: ProcessTableEntry,
|
||||
observation: ProcessIdentityObservation | undefined,
|
||||
): ProcessOwnershipFact => {
|
||||
const before = identityBefore.get(process.pid) ?? {
|
||||
state: "unavailable" as const,
|
||||
reason: "process identity was not returned during before observation",
|
||||
};
|
||||
const after = identityAfter.get(process.pid) ?? {
|
||||
const after = observation ?? {
|
||||
state: "unavailable" as const,
|
||||
reason: "process identity was not returned during after observation",
|
||||
};
|
||||
@@ -664,6 +679,14 @@ export const readProcessOwnershipFacts = async (
|
||||
token,
|
||||
identityAfter: after,
|
||||
};
|
||||
};
|
||||
const facts = processes.map((process): ProcessOwnershipFact => {
|
||||
const after = identityAfter.get(process.pid);
|
||||
const original = observedAfter.get(process.pid);
|
||||
const fact = deriveFact(process, after);
|
||||
return after === original
|
||||
? fact
|
||||
: { ...fact, beforeExitSettlement: deriveFact(process, original) };
|
||||
});
|
||||
signal?.throwIfAborted();
|
||||
return facts;
|
||||
|
||||
Reference in new issue
Block a user