mirror of
https://github.com/morluto/rea
synced 2026-10-26 06:16:17 -04:00
fix(ghidra): retain neutral recovery for observed SIGKILL
This commit is contained in:
@@ -24,6 +24,12 @@ undefined. Installation `application.properties` has a fixed 1 MiB read allowanc
|
||||
with no runtime override. The failure retains that allowance and directs recovery
|
||||
at the selected installation metadata.
|
||||
|
||||
Retained process diagnostics can report termination by `SIGKILL`; the signal alone
|
||||
cannot establish an OOM kill. REA gives neutral recovery guidance and preserves the
|
||||
signal. Confirm resource causes from process output or host/container records;
|
||||
operation-scoped JVM `OutOfMemoryError` observations retain their separate resource
|
||||
classification. Automatic kernel or cgroup OOM attribution is not implemented.
|
||||
|
||||
Provider selection and profile identity follow
|
||||
[MCP contracts](mcp-contracts.md#identity-and-discovery). One deep
|
||||
provider stays bound to the target; runtime failure never selects another
|
||||
|
||||
@@ -3690,6 +3690,37 @@ const issueOutput = [
|
||||
].join("\n");
|
||||
|
||||
describe("Ghidra OOME error projection", () => {
|
||||
it("preserves observed SIGKILL without guessing its cause or installation recovery", async () => {
|
||||
const projected = await projectFailure("process", {
|
||||
exit_code: null,
|
||||
exit_signal: "SIGKILL",
|
||||
failure_output: failureOutput(),
|
||||
});
|
||||
expect(projected.code).toBe("execution_failure");
|
||||
expect(projected.message).toContain("SIGKILL");
|
||||
expect(projected.message).toContain("does not establish its cause");
|
||||
expect(projected.remediation.action).toContain(
|
||||
"host or container termination records",
|
||||
);
|
||||
expect(projected.remediation.action).not.toContain("rea doctor");
|
||||
expect(projected.remediation.action).not.toContain(
|
||||
"GHIDRA_HEADLESS_MAXMEM",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps operation-scoped JVM memory evidence stronger than an exit signal", async () => {
|
||||
const projected = await projectFailure("process", {
|
||||
exit_signal: "SIGKILL",
|
||||
failure_output: failureOutput(
|
||||
"",
|
||||
"java.lang.OutOfMemoryError: Java heap space",
|
||||
),
|
||||
});
|
||||
expect(projected.code).toBe("resource_constraint");
|
||||
expect(projected.message).toContain("Java heap space");
|
||||
expect(projected.remediation.action).toContain("GHIDRA_HEADLESS_MAXMEM");
|
||||
});
|
||||
|
||||
it("recognizes the headless analyzer's real detail-before-class output", async () => {
|
||||
const projected = await projectFailure("process", {
|
||||
stdout: output(issueOutput),
|
||||
|
||||
@@ -1008,6 +1008,18 @@ const projectPrimarySessionError = (
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (
|
||||
(failure.kind === "start" ||
|
||||
failure.kind === "process" ||
|
||||
failure.kind === "protocol") &&
|
||||
failure.diagnostics.exit_signal === "SIGKILL"
|
||||
)
|
||||
return new ProviderAdapterError("ghidra", operation, {
|
||||
...context,
|
||||
userMessage: `Ghidra process diagnostics report termination by SIGKILL. The signal alone does not establish its cause or an out-of-memory failure.${uncertainty === undefined ? "" : ` ${uncertainty}`}`,
|
||||
remediationAction:
|
||||
"Review the retained process output and host or container termination records before choosing a resource-specific remedy. Export useful Evidence, close the binary and resolve any cleanup failure, then call open_binary for the same target to start a new Ghidra session. Session-only annotations are not retained.",
|
||||
});
|
||||
const exited = exitedProviderMessage(operation, failure, health);
|
||||
if (exited !== undefined)
|
||||
return new ProviderAdapterError("ghidra", operation, {
|
||||
|
||||
Reference in New Issue
Block a user