🤔 Background
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.57
src/runner.sh: line 376: [: abc: integer expression expected
src/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:
$ /opt/homebrew/bin/bash ./bashunit --jobs abc tests/ # bash 5.3.15
All tests passed
$ echo $?
0
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.
🤔 Background
src/main.shresolves--jobs autoto an integer and carries this comment:The
elsebranch then assigns$2verbatim, so the stated invariant is never enforced. Nothing else validates it, andBASHUNIT_PARALLEL_JOBSfrom the environment bypasses this code entirely.Observed
bashunit::runner::wait_for_job_slotcompares the running-job count againstmax_jobswith[ ... ], which errors (status 2) on a non-integer operand. The two execution paths then diverge:Bash 3.x (polling fallback,
src/runner.sh:376) — thebreakguard never succeeds, so the loop never exits. The run hangs, emitting the same error forever:Bash 4.3+ (
wait -npath,src/runner.sh:363) — thewhileguard 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:Suggested fix
Validate at the boundary the same way
bashunit::main::set_shard_or_exitalready does — reject a--jobsvalue that is not a non-negative integer with a clear error and non-zero exit, and apply the same check whenBASHUNIT_PARALLEL_JOBScomes from the environment. Worth makingwait_for_job_slotfail safe rather than loop forever regardless.