diff --git a/src/config/env.sh b/src/config/env.sh index 24c9decc..cc488f22 100644 --- a/src/config/env.sh +++ b/src/config/env.sh @@ -949,9 +949,9 @@ function bashunit::env::cleanup_run_output_dir() { # subshells never inherit EXIT traps, so a parallel worker cannot remove the # directory mid-run. # Set while a bootstrap file is being sourced, cleared immediately after. A -# `source` that never returns -- special-builtin semantics on a syntax error or -# a bare `exit` -- leaves it set, which is the only trace such a failure leaves -# (#1179). +# `source` that never returns -- a syntax error while `set -e` is active, or a +# bare `exit` in the file -- leaves it set, which is the only trace such a +# failure leaves (#1179). _BASHUNIT_LOADING_BOOTSTRAP="" function bashunit::env::report_unfinished_bootstrap() { diff --git a/src/main/bench.sh b/src/main/bench.sh index 8fe463a6..ba80e457 100644 --- a/src/main/bench.sh +++ b/src/main/bench.sh @@ -87,9 +87,11 @@ function bashunit::main::cmd_bench() { # Export all variables from the env file so they're available in subshells # (e.g., process substitution used in load_test_files) set -o allexport - # `source` is a special builtin: a syntax error in the file, or a bare - # `exit`, ends this shell here and nothing below runs. The marker is what - # the EXIT trap reports when it was never cleared (#1181). + # Two ways this never returns: a syntax error makes `source` return + # non-zero, which ends the shell because `set -e` is active here, and a + # bare `exit` in the file ends it regardless. Either way nothing below + # runs, so the marker is what the EXIT trap reports when it was never + # cleared (#1181). _BASHUNIT_LOADING_BOOTSTRAP="$boot_file" # shellcheck disable=SC1090,SC2086 source "$boot_file" ${BASHUNIT_BOOTSTRAP_ARGS:-} @@ -145,12 +147,11 @@ function bashunit::main::cmd_bench() { # error left the run with no tests, no summary and exit 0, and CI passed # having executed nothing (#1179). if [ -f "${BASHUNIT_BOOTSTRAP:-}" ]; then - # `source` is a POSIX special builtin: a syntax error in the file, or a - # bare `exit`, terminates this shell right here -- so nothing after the - # call can report it, and the run ended with no tests, no summary and - # exit 0 (#1179). Pre-validating with `bash -n` would cost an interpreter - # fork on every invocation, which the cold-start budget forbids, so leave - # a marker instead and let the EXIT trap notice it was never cleared. + # Two ways this never returns: a syntax error makes `source` return + # non-zero, which ends the shell because `set -e` is active here, and a + # bare `exit` in the file ends it regardless. Either way nothing below + # runs, so the marker is what the EXIT trap reports when it was never + # cleared (#1179). _BASHUNIT_LOADING_BOOTSTRAP="$BASHUNIT_BOOTSTRAP" # shellcheck disable=SC1090,SC2086 source "$BASHUNIT_BOOTSTRAP" ${BASHUNIT_BOOTSTRAP_ARGS:-} diff --git a/src/main/subcommands.sh b/src/main/subcommands.sh index 24232a8c..f9b1a4be 100644 --- a/src/main/subcommands.sh +++ b/src/main/subcommands.sh @@ -43,9 +43,11 @@ function bashunit::main::cmd_doc() { exit 1 fi else - # `source` is a special builtin: a syntax error in the file, or a bare - # `exit`, ends this shell here and nothing below runs. The marker is what - # the EXIT trap reports when it was never cleared (#1181). + # Two ways this never returns: a syntax error makes `source` return + # non-zero, which ends the shell because `set -e` is active here, and a + # bare `exit` in the file ends it regardless. Either way nothing below + # runs, so the marker is what the EXIT trap reports when it was never + # cleared (#1181). _BASHUNIT_LOADING_BOOTSTRAP="$boot_file" # shellcheck disable=SC1090,SC2086 source "$boot_file" ${BASHUNIT_BOOTSTRAP_ARGS:-} diff --git a/src/main/test.sh b/src/main/test.sh index 337bc73b..dba86810 100644 --- a/src/main/test.sh +++ b/src/main/test.sh @@ -326,9 +326,11 @@ function bashunit::main::cmd_test() { # Export all variables from the env file so they're available in subshells # (e.g., process substitution used in load_test_files) set -o allexport - # `source` is a special builtin: a syntax error in the file, or a bare - # `exit`, ends this shell here and nothing below runs. The marker is what - # the EXIT trap reports when it was never cleared (#1181). + # Two ways this never returns: a syntax error makes `source` return + # non-zero, which ends the shell because `set -e` is active here, and a + # bare `exit` in the file ends it regardless. Either way nothing below + # runs, so the marker is what the EXIT trap reports when it was never + # cleared (#1181). _BASHUNIT_LOADING_BOOTSTRAP="$boot_file" # shellcheck disable=SC1090,SC2086 source "$boot_file" ${BASHUNIT_BOOTSTRAP_ARGS:-} @@ -666,12 +668,14 @@ function bashunit::main::cmd_test() { # error left the run with no tests, no summary and exit 0, and CI passed # having executed nothing (#1179). if [ -f "${BASHUNIT_BOOTSTRAP:-}" ]; then - # `source` is a POSIX special builtin: a syntax error in the file, or a - # bare `exit`, terminates this shell right here -- so nothing after the - # call can report it, and the run ended with no tests, no summary and - # exit 0 (#1179). Pre-validating with `bash -n` would cost an interpreter - # fork on every invocation, which the cold-start budget forbids, so leave - # a marker instead and let the EXIT trap notice it was never cleared. + # Two ways this never returns: a syntax error makes `source` return + # non-zero, which ends the shell because `set -e` is active here, and a + # bare `exit` in the file ends it regardless of `set -e`. Either way + # nothing after the call runs, and the run ended with no tests, no summary + # and exit 0 (#1179). Pre-validating with `bash -n` would cost an + # interpreter fork on every invocation, which the cold-start budget + # forbids, so leave a marker and let the EXIT trap notice it was never + # cleared. _BASHUNIT_LOADING_BOOTSTRAP="$BASHUNIT_BOOTSTRAP" # shellcheck disable=SC1090,SC2086 source "$BASHUNIT_BOOTSTRAP" ${BASHUNIT_BOOTSTRAP_ARGS:-}