You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
--jobs with a non-integer value hangs on Bash 3.x and is silently ignored on Bash 4.3+ #873
src/main.sh resolves --jobs auto to an integer and carries this comment:
# "auto" caps at the detected core count; wait_for_job_slot needs an# integer, so resolve it here rather than leaking the string downstream.
The else branch then assigns $2 verbatim, so the stated invariant is never enforced. Nothing else validates it, and BASHUNIT_PARALLEL_JOBS from the environment bypasses this code entirely.
Observed
bashunit::runner::wait_for_job_slot compares the running-job count against max_jobs with [ ... ], which errors (status 2) on a non-integer operand. The two execution paths then diverge:
Bash 3.x (polling fallback, src/runner.sh:376) — the break guard never succeeds, so the loop never exits. The run hangs, emitting the same error forever:
$ ./bashunit --jobs abc tests/ # /bin/bash 3.2.57src/runner.sh: line 376: [: abc: integer expression expectedsrc/runner.sh: line 376: [: abc: integer expression expected... # killed at 15s, no progress
Bash 4.3+ (wait -n path, src/runner.sh:363) — the while guard fails, the loop body never runs, and the concurrency limit is silently dropped:
So the same command hangs on the bash macOS ships and silently ignores the limit on a modern one.
Related
Same class as #871 (unvalidated CLI input). --output <value> is also accepted with any string and silently ignored:
$ ./bashunit --output nonsense tests/ All tests passed # exit 0, default format
Suggested fix
Validate at the boundary the same way bashunit::main::set_shard_or_exit already does — reject a --jobs value that is not a non-negative integer with a clear error and non-zero exit, and apply the same check when BASHUNIT_PARALLEL_JOBS comes from the environment. Worth making wait_for_job_slot fail safe rather than loop forever regardless.
--shard is the exception: bashunit::main::set_shard_or_exit validates it and exits non-zero with a clear message. That is the pattern the rest should follow.
The practical impact is the same shape as #871 — a CI job configured with --coverage-min 80 that gets a bad value reports success without enforcing the threshold.
Activity
Chemaclass commentedon Jul 25, 2026
Swept every value-taking flag with a non-integer and a negative value. None of the numeric flags validate their argument — all exit
0:--jobs abc--jobs -5--retry abc--retry -3--test-timeout abc--seed abc--output nonsense--coverage-min abc--coverage-minis the one that surfaces anything at all, and only as an unhandled[failure:--shardis the exception:bashunit::main::set_shard_or_exitvalidates it and exits non-zero with a clear message. That is the pattern the rest should follow.The practical impact is the same shape as #871 — a CI job configured with
--coverage-min 80that gets a bad value reports success without enforcing the threshold.Chemaclass commentedon Jul 26, 2026
Done in #874 (merged).