fix(env): stop an unreadable environment setting from picking a wrong default - #1880
fix(env): stop an unreadable environment setting from picking a wrong default#1880CaptainMittens wants to merge 1 commit into
Conversation
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
c9fd0a7 to
30dcb62
Compare
|
Same shape as #1922: an input the code cannot read becomes a plausible value, and nothing downstream can tell it from a real one. Here it is
This is one of four from a single scan for siblings of #1875's shape — #1875, #1877, #1880, #1881. Context for the set, and a question about the two still unfiled, is on #1877. |
|
Thank you for the detailed reproduce-first analysis and for keeping policy at the individual call sites instead of hiding it in the shared parser. This changes hook deadlines, worker timeout handling, and restart policy across the CLI and MCP paths, so we need more time to review compatibility and failure behavior before making a decision. No additional information is requested from you at this stage. |
|
Approved. Three real bugs, and the first one is nastier than the table conveys. I checked your headline evidence and it is exact. The comment above int v = atoi(env);
if (v < HA_DEADLINE_MIN_MS) { return HA_DEADLINE_MIN_MS; } /* 50 */So a typo in the one setting that exists to make that budget more generous hands back 50 ms — six times shorter than the 300 ms already documented as too short. Someone raising the deadline because their hook never fires would make it strictly worse and see nothing.
And One thing I chased and it comes out clean. Smaller things done right: the leading-blank refusal ( Status: cleared, reviewed, approved. Working the bug class from #1875 rather than the bug — confidence pair in #1877, timestamps in #1881, environment here — is why these three read as one piece of work instead of three coincidences. |
… default
atoi and atol answer 0 for text they cannot read, and 0 is a real setting at
three places in this project. So a typo, a trailing unit such as "30s", or a
stray space silently chose a value nobody asked for, and nothing on screen
said the setting had been dropped.
src/mcp/index_supervisor.c CBM_INDEX_WORKER_TIMEOUT_S
src/cli/hook_augment.c CBM_HOOK_DEADLINE_MS
src/mcp/mcp.c CBM_INDEX_MAX_RESTARTS
CBM_HOOK_DEADLINE_MS was the worst of the three. atoi answered 0, 0 is below
HA_DEADLINE_MIN_MS, and the clamp then handed back 50 ms -- the SHORTEST
deadline the setting allows, for a setting whose only purpose is to give the
hook more room. The comment above that function records a hunt for hook runs
that never finished, 0 of 24 real sessions, which is the exact symptom a
silently-shortened deadline produces.
CBM_INDEX_MAX_RESTARTS lost twice. A typo kept the default of 100, and
CBM_INDEX_MAX_RESTARTS=0 -- which reads as "do not restart" to anybody who
sets it -- also kept 100. The setting did the opposite of the request.
CBM_INDEX_WORKER_TIMEOUT_S fell through to the 15-minute default, so a test
set to give up after 30 seconds hung for 15 minutes with nothing to explain
why.
The fix adds one helper rather than three copies of the same check:
bool cbm_env_long(const char *name, long *out);
It answers true only when the variable is set, is not empty, and reads
cleanly from its first character to its last. It holds no policy -- no
minimum, no maximum, no default -- because the three sites disagree on all
three, and a helper that guessed would be wrong at two of them. The shape is
the one src/main.c:1104 already uses: an end pointer, errno, and a check that
nothing was left over. It also refuses a leading blank, which strtol would
otherwise step over, so " 5" is a slip rather than the number 5.
Each site keeps its own rule:
worker timeout an unreadable value keeps the 15-minute default AND logs
the value it dropped
restart cap 0 now means no restarts; an unreadable value keeps 100
AND logs the value it dropped
hook deadline an unreadable value now yields HA_DEADLINE_DEFAULT_MS,
not the floor. This one stays silent on purpose: the file
includes no log header and writes no stderr, because its
output is hook protocol.
The restart-cap parse was lifted out of a very large function into a named
index_restart_cap(), so it can be read and reached on its own.
Four tests come with the change. The two that pin the user-visible behaviour
were seen failing before the fix:
FAIL tests/test_cli.c:402: ms == 50, expected HOOK_DEADLINE_DEFAULT == 2000
(with "unreadable value \"abc\" gave 50 ms" printed above it)
FAIL tests/test_cli.c:434: cbm_index_restart_cap_for_testing() == 100,
expected 0 == 0
After the fix, TEST_SUITES="platform cli mcp" reports 518 passed, 2 failed.
The full suite reports 7635 passed, 2 failed. Both failures are in
tests/test_cli.c (lines 1826 and 6802), print "error: one or more agent
cleanup operations failed", and reproduce on a clean tree without this
change -- they depend on the coding agents installed on the machine.
make -f Makefile.cbm lint-ci passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
30dcb62 to
6b801ee
Compare
|
Rebased onto Posting the local test result too, because it looks alarming and is not. If you run this branch's suite yourself you will see failures, and I would rather you had the comparison up front than spend time on it. On this machine, same worktree, same
The branch fails fewer than the base it sits on, and its two are a strict subset of main's six. They are the same two test functions — this branch adds 81 lines to
Main's other four are Two machine conditions explain them, and neither exists on your runners: OpenCode is installed here. The failing runs print No permanent daemon is running. The agent-client install/uninstall and cohort-drain assertions cannot drain a cohort cleanly without one, which is why the failing set is not even stable between runs on the same tree. I have opened #2019 for the first of those, which fixes the Nothing needed from you on this thread. #1880 itself is unchanged apart from the rebase. |
What this fixes
atoiandatolanswer0for text they cannot read, and0is a realsetting at three places in this project. So a typo, a trailing unit such as
30s, or a stray space silently chose a value nobody asked for — and nothingon screen said the setting had been dropped.
src/cli/hook_augment.cCBM_HOOK_DEADLINE_MSsrc/mcp/mcp.cCBM_INDEX_MAX_RESTARTS=0src/mcp/index_supervisor.cCBM_INDEX_WORKER_TIMEOUT_S1.
CBM_HOOK_DEADLINE_MS— a typo bought the shortest possible deadlineatoianswers0,0is belowHA_DEADLINE_MIN_MS, and the clamp handedback 50 ms — for a setting whose only purpose is to give the hook more
room. The comment directly above that function records a hunt for hook runs
that never finished, 0 of 24 real sessions, which is the exact symptom a
silently-shortened deadline produces.
2.
CBM_INDEX_MAX_RESTARTS— the setting did the opposite of the requestTwo ways to lose. A typo kept the default of 100. And
CBM_INDEX_MAX_RESTARTS=0— which reads as "do not restart" to anybody whosets it — also kept 100.
3.
CBM_INDEX_WORKER_TIMEOUT_S— a 30-second test hung for 15 minutesThe comment above this override says it exists to tighten the timeout for
tests.
atolanswered0for30sor a stray space,0failed the> 0test, and the 15-minute default came back with nothing to explain it.
The fix
One helper, not three copies of the same check:
It answers true only when the variable is set, is not empty, and reads cleanly
from its first character to its last. It holds no policy — no minimum, no
maximum, no default — because the three sites disagree on all three, and a
helper that guessed would be wrong at two of them.
The shape is the one
src/main.c:1104already uses for--port=: an endpointer,
errno, and a check that nothing was left over. It adds one thing ontop — a refusal of a leading blank, because
strtolsteps over blanks of itsown accord, so
" 5"would otherwise read as the number 5. Theclisuitecaught that during this work.
Each site keeps its own rule:
0now means no restarts; unreadable keeps 100 AND logs the dropped valueHA_DEADLINE_DEFAULT_MS(2000), never the floorhook_augment.cstays silent on purpose: it includes no log header and writesno stderr, because its output is hook protocol.
The restart-cap parse was lifted out of a very large function into a named
index_restart_cap(), so it can be read and reached on its own.Tests
Four tests. The two that pin the user-visible behaviour were seen failing
before the fix:
Each carries a positive control first — a good value is still read — so a later
failure points at the unreadable case and not at a reader broken outright.
platform_env_long_reads_a_clean_numbertests/test_platform.cplatform_env_long_refuses_what_it_cannot_readtests/test_platform.ccli_hook_deadline_ignores_an_unreadable_valuetests/test_cli.ccli_index_restart_cap_honours_zero_and_refuses_junktests/test_cli.cTwo
_for_testingwrappers reach the statics, following the convention alreadyused 25 times in
src/cli/cli.h. The deadline wrapper is POSIX-only, matchingthe
#ifndef _WIN32block the function lives in.Checks run
make -f Makefile.cbm test-focused TEST_SUITES="platform cli mcp"518 passed, 2 failed, 6 skippedmake -f Makefile.cbm lint-ci=== CI linters passed ===— exit 0make -f Makefile.cbm cbmmake -f Makefile.cbm test7635 passed, 2 failed, 8 skippedThe two failures are in
tests/test_cli.c(lines 1826 and 6802), printerror: one or more agent cleanup operations failed, and reproduce on a cleantree without this change. They depend on the coding agents installed on the
machine.
How this was found
By scanning for siblings of the parse bug fixed in #1875 — "a parse reports
success while the input stays unread". #1877 fixed the confidence pair from the
same scan. This is the environment-variable group.
Checklist
git commit -s(DCO)make -f Makefile.cbm testrunmake -f Makefile.cbm lint-cirunFixes #1981