fix(signals): name the limiter as a possible cause of a failed sigrok version probe (#6395)
* fix(signals): report a failed sigrok version probe as a configuration error * fix(signals): attribute a failed version probe to the limited probe * fix(signals): name the limiter as a possible cause of a failed version probe The version probe runs under the resource limiter, so a nonzero status can come from prlimit as well as sigrok-cli. Say so in the configuration refusal instead of blaming sigrok-cli alone, and cover a limiter that refuses to start the tool for both decode and discovery. * test(signals): assert limiter probe failures by typed fields The limiter-refused recording test locked English probe wording. Assert the capability-unavailable code, provider, operation, and captured limiter output instead. * fix(signals): record an unattributed version-probe status owner A nonzero resource-limited version probe now reports version_probe_status_owner limiter-or-tool. The limiter-refusal test requires that field, so the old sigrok-cli-only failure no longer passes. --------- Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
2 files changed
+73
-5
No files matched your search
@@ -76,6 +76,21 @@ type Launcher = NonNullable<Parameters<typeof runOwnedCommand>[2]>["launcher"];
|
||||
export const sigrokHostSupported = (platform: NodeJS.Platform): boolean =>
|
||||
platform === "linux";
|
||||
|
||||
/**
|
||||
* A nonzero version probe ran under the resource limiter, so the status is not
|
||||
* attributed to sigrok-cli alone.
|
||||
*/
|
||||
class ResourceLimitedVersionProbeFailure extends Error {
|
||||
readonly statusOwner = "limiter-or-tool" as const;
|
||||
|
||||
constructor() {
|
||||
super(
|
||||
"The resource-limited sigrok-cli --version probe failed; the status may come from the limiter or from sigrok-cli, so inspect both selected installations and the captured output.",
|
||||
);
|
||||
this.name = "ResourceLimitedVersionProbeFailure";
|
||||
}
|
||||
}
|
||||
|
||||
/** Decode selected recordings only, retaining cleanup ownership across failures. */
|
||||
export class SigrokRecordingProvider implements SignalRecordingPort {
|
||||
readonly #resources: ArtifactAnalysisResources;
|
||||
@@ -270,10 +285,9 @@ export class SigrokRecordingProvider implements SignalRecordingPort {
|
||||
{ capturedOutput, userMessage: rejection.message },
|
||||
[rejection],
|
||||
);
|
||||
// The probe runs under the limiter, so either program may own the status.
|
||||
if (output.exitCode !== 0 && phase === "configuration")
|
||||
throw new Error(
|
||||
"The selected sigrok-cli installation failed its --version probe; inspect its captured output.",
|
||||
);
|
||||
throw new ResourceLimitedVersionProbeFailure();
|
||||
if (output.exitCode !== 0)
|
||||
throw new ProviderAdapterError(
|
||||
SIGROK_PROVIDER_IDENTITY.id,
|
||||
@@ -528,6 +542,13 @@ export class SigrokRecordingProvider implements SignalRecordingPort {
|
||||
...(observedOutput === undefined
|
||||
? {}
|
||||
: { capturedOutput: observedOutput }),
|
||||
...(cause instanceof ResourceLimitedVersionProbeFailure
|
||||
? {
|
||||
diagnostics: {
|
||||
version_probe_status_owner: cause.statusOwner,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
userMessage: `${reason} On Linux, configure sigrok-cli 0.7.2 through REA_SIGROK_COMMAND and util-linux prlimit through REA_SIGROK_PRLIMIT_COMMAND (default /usr/bin/prlimit).`,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -95,6 +95,15 @@ const fixture = async (
|
||||
const configuredCommand =
|
||||
mode === "symlink" ? join(directory, "configured-tool") : script;
|
||||
if (mode === "symlink") await symlink(script, configuredCommand);
|
||||
// A separate limiter that refuses to start the wrapped tool.
|
||||
const limiter = join(directory, "limiter.mjs");
|
||||
if (mode === "limiter-refused") {
|
||||
await writeFile(
|
||||
limiter,
|
||||
"console.error('prlimit: failed to execute sigrok-cli'); process.exitCode = 1;\n",
|
||||
);
|
||||
await chmod(limiter, 0o700);
|
||||
}
|
||||
const controller = new AbortController();
|
||||
let calls = 0;
|
||||
let mayClean = !failCleanup;
|
||||
@@ -104,7 +113,8 @@ const fixture = async (
|
||||
{
|
||||
...process.env,
|
||||
REA_SIGROK_COMMAND: configuredCommand,
|
||||
REA_SIGROK_PRLIMIT_COMMAND: configuredCommand,
|
||||
REA_SIGROK_PRLIMIT_COMMAND:
|
||||
mode === "limiter-refused" ? limiter : configuredCommand,
|
||||
},
|
||||
async (input) => {
|
||||
calls++;
|
||||
@@ -127,7 +137,10 @@ const fixture = async (
|
||||
const spawned = await spawnOwnedProviderProcess({
|
||||
...input,
|
||||
command: process.execPath,
|
||||
arguments: [script, ...input.arguments],
|
||||
arguments: [
|
||||
mode === "limiter-refused" ? limiter : script,
|
||||
...input.arguments,
|
||||
],
|
||||
expectedCommand: process.execPath,
|
||||
});
|
||||
if (mode === "wait" && !input.arguments.includes("--version"))
|
||||
@@ -1415,3 +1428,37 @@ it("classifies completed nonzero version probes as configuration failures for bo
|
||||
}
|
||||
expect(f.calls()).toBe(2);
|
||||
});
|
||||
|
||||
it("does not blame sigrok-cli alone when the limiter fails the version probe", async () => {
|
||||
const f = await fixture("limiter-refused");
|
||||
for (const [operation, task] of [
|
||||
[
|
||||
"decode_signal_recording",
|
||||
() => f.service.decode({ path: f.path, decoders: "uart" }),
|
||||
],
|
||||
["inspect_signal_decoders", () => f.service.inspectDecoders({})],
|
||||
] as const) {
|
||||
const result = await task();
|
||||
if (result.ok) throw new Error("Expected version admission refusal");
|
||||
expect(result.error).toMatchObject({
|
||||
_tag: "AnalysisCapabilityUnavailableError",
|
||||
providerId: "sigrok-recording",
|
||||
operation,
|
||||
});
|
||||
expect(projectAnalysisError(result.error)).toMatchObject({
|
||||
code: "capability_unavailable",
|
||||
details: {
|
||||
provider_id: "sigrok-recording",
|
||||
operation,
|
||||
// Absent when the probe is reported as a sigrok-cli failure alone.
|
||||
diagnostics: { version_probe_status_owner: "limiter-or-tool" },
|
||||
captured_output: {
|
||||
exit_code: 1,
|
||||
stdout: "",
|
||||
stderr: "prlimit: failed to execute sigrok-cli\n",
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
expect(f.calls()).toBe(2);
|
||||
});
|
||||
Reference in new issue
Block a user