cmd/run, test/system: Handle exit code 127 in 'run' from forwarded call

When 'toolbox run' is invoked on the host, an exit code of 127 from
'podman exec' means either that the specified command couldn't be found
or that the working directory didn't exist.  The only way to tell these
two scenarios apart is to actually look inside the container.

Secondly, Toolbx containers always have an executable toolbox(1) binary
at /usr/bin/toolbox and it's assumed that /usr/bin is always part of the
PATH environment variable.

When 'toolbox run toolbox ...' is invoked, the inner toolbox(1)
invocation will be forwarded back to the host by the Toolbx container's
/usr/bin/toolbox, which is always present as an executable.  Hence, if
the outer 'podman exec' on the host fails with an exit code of 127,
then it doesn't mean that the container didn't have a toolbox(1)
executable, but that some subordinate process started by the container's
toolbox(1) failed with that exit code.

Therefore, handle this as a special case to avoid losing the exit code.
Otherwise, it leads to:
  $ toolbox run toolbox run non-existent-command
  bash: line 1: exec: non-existent-command: not found
  Error: command non-existent-command not found in container
      fedora-toolbox-40
  $ echo "$?"
  0

Instead, it will now be:
  $ toolbox run toolbox run non-existent-command
  bash: line 1: exec: non-existent-command: not found
  Error: command non-existent-command not found in container
      fedora-toolbox-40
  $ echo "$?"
  127

https://github.com/containers/toolbox/issues/957
https://github.com/containers/toolbox/pull/1052
This commit is contained in:
Debarshi Ray 2024-09-09 19:41:45 +02:00
parent 1a88195729
commit 26a76f2d7f
2 changed files with 20 additions and 0 deletions

View File

@ -462,6 +462,8 @@ func runCommandWithFallbacks(container string,
container)
return &exitError{exitCode, errors.New(errMsg)}
}
} else if command[0] == "toolbox" {
return &exitError{exitCode, nil}
} else {
return nil
}

View File

@ -93,3 +93,21 @@ teardown() {
assert_line --index 2 "Error: failed to invoke command /etc in container $default_container"
assert [ ${#stderr_lines[@]} -eq 3 ]
}
@test "run: Try a non-existent command (forwarded to host)" {
local cmd="non-existent-command"
local default_container
default_container="$(get_system_id)-toolbox-$(get_system_version)"
create_default_container
run -127 --keep-empty-lines --separate-stderr "$TOOLBX" run toolbox run "$cmd"
assert_failure
assert [ ${#lines[@]} -eq 0 ]
lines=("${stderr_lines[@]}")
assert_line --index 0 "bash: line 1: exec: $cmd: not found"
assert_line --index 1 "Error: command $cmd not found in container $default_container"
assert [ ${#stderr_lines[@]} -eq 2 ]
}