--- id: "bug-1796" status: "open" status_updated: "2026-09-24" status_note: "qctrl/hostctrl perror() prints stale errno instead of RPC rc (src/harness/test.c)" component: "controller" severity: "unknown" timestamp: "2026-09-09T22:00:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/controller/testsuite/test.c (cmd_qctrl", "cmd_hostctrl", "cmd_jobkill RPC-error return paths)"] tags: ["controller", "testsuite", "xce_test", "cmd_qctrl", "cmd_hostctrl", "cmd_jobkill", "perror", "errno", "misleading-diagnostic", "xce-test-cli-ux", "task-4.2", "pre-existing", "deferred"] related: [] legacy: true --- # bug-1796: cmd_qctrl/cmd_hostctrl/cmd_jobkill's RPC-failure branches perror() a fixed label (e.g ## Description cmd_qctrl/cmd_hostctrl/cmd_jobkill's RPC-failure branches perror() a fixed label (e.g. "xcecli_queuectrl") without ever setting errno to reflect the RPC's actual returned status, so the printed reason (e.g. "Interrupted system call", "Resource temporarily unavailable", "Inappropriate ioctl for device") is whatever errno happened to be left over from an unrelated earlier libc call in the same process, not the real failure reason. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause Each of these commands does `if (rc < 0) { perror("xcecli_..."); return rc; }` where `rc` is the RPC's own negative-errno-style return value (e.g. a clean -ENOENT for "no such queue/host"), but perror() always reads the CURRENT process errno, not `rc` -- and nothing in this branch ever does `errno = -rc` first. Found during xce-test-cli-ux task 4.2's live confirmation-gate verification: a bypassed qctrl/hostctrl RPC against a deliberately bogus (nonexistent) queue/host name printed different, unrelated-looking error text across different runs of the SAME scenario, root-caused (and independently reproduced 3 times by the task 4.2 reviewer) to stale errno left over from prior, unrelated syscalls/signal-decline paths in the same process -- e.g. a destructive-command Ctrl-C decline explicitly sets errno = EINTR at its own call site and never resets it, so a LATER unrelated RPC failure in the same session then misreports itself as "Interrupted system call". Confirmed pre-existing (commit 41f56fa6e, 2025-11-05), predating the whole xce-test-cli-ux spec; NOT a defect in the interruptible-call adapter (tasks 1.4/3.2) or the confirmation gate (task 2.1/3.3) -- both were independently confirmed to behave correctly in every case tested, this is purely a misleading-diagnostic-text bug. ## Fix NOT YET FIXED (found and deliberately deferred -- out of boundary for task 4.2, a pure live-verification task with no source changes permitted). Recommended: set `errno = -rc;` immediately before each `perror(...)` call on these RPC-error paths (or replace with `fprintf(stderr, "...: %s\n", strerror(-rc));` to avoid the errno indirection entirely), and audit other cmd_* handlers for the same perror()-without-errno-set pattern. ## Verification _Not recorded (migrated from buglog.json)._ ## References _Not recorded (migrated from buglog.json)._