mirror of
https://github.com/crosstool-ng/crosstool-ng.git
synced 2025-02-01 00:45:43 +00:00
scripts: add option to start an interactive debug shell
Add an option that, when a command fails: - starts an interactive shell with the failed command's environment - attempts re-execution of the failed command, continues, or aborts at user's whim. Before starting the debug-shell, the backtrace is printed. When exiting for an abort, the standard error message is printed. Based on an idea and a patch from: Johannes Stezenbach <js@sig21.net> http://sourceware.org/ml/crossgcc/2012-09/msg00144.html Signed-off-by: Johannes Stezenbach <js@sig21.net> [yann.morin.1998@free.fr: integrate in the fault handler] Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> Acked-by: Johannes Stezenbach <js@sig21.net> Patchwork-Id: 191571 Patchwork-Id: 191668
This commit is contained in:
parent
df3be9eef3
commit
dd98145bc1
@ -87,4 +87,23 @@ config NO_OVERIDE_LC_MESSAGES
|
||||
|
||||
Say N, please.
|
||||
|
||||
config DEBUG_INTERACTIVE
|
||||
bool
|
||||
prompt "Interactive shell on failed commands"
|
||||
help
|
||||
If you say 'y' here, then an interactive shell will be spawned for
|
||||
each failed command.
|
||||
|
||||
This shell will have the same environment that the failed command
|
||||
was run with, and the working directory will be set to the directory
|
||||
the failed command was run in.
|
||||
|
||||
After you fix the issue, you can exit the interactive shell with any
|
||||
of these exit codes:
|
||||
1 the issue was fixed, continue the build with the next command
|
||||
2 the issue was fixed, re-run the failed command
|
||||
3 abort the build
|
||||
|
||||
Note: '2' is only possible for commands run via CT_DoExecLog, though.
|
||||
|
||||
endif
|
||||
|
@ -25,6 +25,14 @@
|
||||
. .config.2
|
||||
# Yes! We can do full logging from now on!
|
||||
|
||||
# If we want an interactive debug-shell, we must ensure these FDs
|
||||
# are indeed connected to a terminal (and not redirected in any way).
|
||||
if [ "${CT_DEBUG_INTERACTIVE}" = "y" -a ! \( -t 0 -a -t 6 -a -t 2 \) ]; then
|
||||
CT_DoLog ERROR "Can't spawn interactive debug-shell,"
|
||||
CT_DoLog ERROR "because stdout/stderr has been redirected."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Override the locale early, in case we ever translate crosstool-NG messages
|
||||
if [ -z "${CT_NO_OVERIDE_LC_MESSAGES}" ]; then
|
||||
export LC_ALL=C
|
||||
|
@ -5,6 +5,8 @@
|
||||
# Prepare the fault handler
|
||||
CT_OnError() {
|
||||
local ret=$?
|
||||
local result
|
||||
local old_trap
|
||||
local intro
|
||||
local file line func
|
||||
local step step_depth
|
||||
@ -35,6 +37,62 @@ CT_OnError() {
|
||||
CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
|
||||
intro=" called from"
|
||||
done
|
||||
|
||||
# If the user asked for interactive debugging, dump him/her to a shell
|
||||
if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
|
||||
# We do not want this sub-shell exit status to be caught, because
|
||||
# it is absolutely legit that it exits with non-zero.
|
||||
# Save the trap handler to restore it after our debug-shell
|
||||
old_trap="$(trap -p ERR)"
|
||||
trap -- ERR
|
||||
(
|
||||
exec >&6
|
||||
printf "\r \n\nCurrent command"
|
||||
if [ -n "${cur_cmd}" ]; then
|
||||
printf ":\n %s\n" "${cur_cmd}"
|
||||
else
|
||||
printf " (unknown), "
|
||||
fi
|
||||
printf "exited with error code: %d\n" ${ret}
|
||||
printf "Please fix it up and finish by exiting the shell with one of these values:\n"
|
||||
printf " 1 fixed, continue with next build command\n"
|
||||
if [ -n "${cur_cmd}" ]; then
|
||||
printf " 2 repeat this build command\n"
|
||||
fi
|
||||
printf " 3 abort build\n\n"
|
||||
while true; do
|
||||
${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
|
||||
result=$?
|
||||
case $result in
|
||||
1) printf "\nContinuing past the failed command.\n\n"
|
||||
break
|
||||
;;
|
||||
2) if [ -n "${cur_cmd}" ]; then
|
||||
printf "\nRe-trying last command.\n\n"
|
||||
break
|
||||
fi
|
||||
;;&
|
||||
3) break;;
|
||||
*) printf "\nPlease exit with one of these values:\n"
|
||||
printf " 1 fixed, continue with next build command\n"
|
||||
if [ -n "${cur_cmd}" ]; then
|
||||
printf " 2 repeat this build command\n"
|
||||
fi
|
||||
printf " 3 abort build\n"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
exit $result
|
||||
)
|
||||
result=$?
|
||||
# Restore the trap handler
|
||||
eval "${old_trap}"
|
||||
case "${result}" in
|
||||
1) rm -f "${CT_WORK_DIR}/backtrace"; return;;
|
||||
2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
|
||||
# 3 is an abort, continue...
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# And finally, in top-level shell, print some hints
|
||||
@ -157,10 +215,11 @@ CT_DoLog() {
|
||||
# Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
|
||||
CT_DoExecLog() {
|
||||
local level="$1"
|
||||
local cur_cmd
|
||||
shift
|
||||
(
|
||||
for i in "$@"; do
|
||||
tmp_log+="'${i}' "
|
||||
cur_cmd+="'${i}' "
|
||||
done
|
||||
while true; do
|
||||
case "${1}" in
|
||||
@ -168,8 +227,39 @@ CT_DoExecLog() {
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
CT_DoLog DEBUG "==> Executing: ${tmp_log}"
|
||||
"${@}" 2>&1 |CT_DoLog "${level}"
|
||||
# This while-loop goes hand-in-hand with the ERR trap handler:
|
||||
# - if the command terminates successfully, then we hit the break
|
||||
# statement, and we exit the loop
|
||||
# - if the command terminates in error, then the ERR handler kicks
|
||||
# in, then:
|
||||
# - if the user did *not* ask for interactive debugging, the ERR
|
||||
# handler exits, and we hit the end of the sub-shell
|
||||
# - if the user did ask for interactive debugging, the ERR handler
|
||||
# spawns a shell. Upon termination of this shell, the ERR handler
|
||||
# examines the exit status of the shell:
|
||||
# - if 1, the ERR handler returns; then we hit the else statement,
|
||||
# then the break, and we exit the 'while' loop, to continue the
|
||||
# build;
|
||||
# - if 2, the ERR handler touches the repeat file, and returns;
|
||||
# then we hit the if statement, and we loop for one more
|
||||
# iteration;
|
||||
# - if 3, the ERR handler exits with the command's exit status,
|
||||
# and we're dead;
|
||||
# - for any other exit status of the shell, the ERR handler
|
||||
# prints an informational message, and respawns the shell
|
||||
#
|
||||
# This allows a user to get an interactive shell that has the same
|
||||
# environment (PATH and so on) that the failed command was ran with.
|
||||
while true; do
|
||||
rm -f "${CT_BUILD_DIR}/repeat"
|
||||
CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
|
||||
"${@}" 2>&1 |CT_DoLog "${level}"
|
||||
if [ -f "${CT_BUILD_DIR}/repeat" ]; then
|
||||
continue
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
)
|
||||
# Catch failure of the sub-shell
|
||||
[ $? -eq 0 ]
|
||||
|
Loading…
x
Reference in New Issue
Block a user