1.1 --- a/config/global/ct-behave.in Sun Oct 14 23:46:15 2012 +0000
1.2 +++ b/config/global/ct-behave.in Sat Oct 06 23:48:07 2012 +0200
1.3 @@ -87,4 +87,23 @@
1.4
1.5 Say N, please.
1.6
1.7 +config DEBUG_INTERACTIVE
1.8 + bool
1.9 + prompt "Interactive shell on failed commands"
1.10 + help
1.11 + If you say 'y' here, then an interactive shell will be spawned for
1.12 + each failed command.
1.13 +
1.14 + This shell will have the same environment that the failed command
1.15 + was run with, and the working directory will be set to the directory
1.16 + the failed command was run in.
1.17 +
1.18 + After you fix the issue, you can exit the interactive shell with any
1.19 + of these exit codes:
1.20 + 1 the issue was fixed, continue the build with the next command
1.21 + 2 the issue was fixed, re-run the failed command
1.22 + 3 abort the build
1.23 +
1.24 + Note: '2' is only possible for commands run via CT_DoExecLog, though.
1.25 +
1.26 endif
2.1 --- a/scripts/crosstool-NG.sh.in Sun Oct 14 23:46:15 2012 +0000
2.2 +++ b/scripts/crosstool-NG.sh.in Sat Oct 06 23:48:07 2012 +0200
2.3 @@ -25,6 +25,14 @@
2.4 . .config.2
2.5 # Yes! We can do full logging from now on!
2.6
2.7 +# If we want an interactive debug-shell, we must ensure these FDs
2.8 +# are indeed connected to a terminal (and not redirected in any way).
2.9 +if [ "${CT_DEBUG_INTERACTIVE}" = "y" -a ! \( -t 0 -a -t 6 -a -t 2 \) ]; then
2.10 + CT_DoLog ERROR "Can't spawn interactive debug-shell,"
2.11 + CT_DoLog ERROR "because stdout/stderr has been redirected."
2.12 + exit 1
2.13 +fi
2.14 +
2.15 # Override the locale early, in case we ever translate crosstool-NG messages
2.16 if [ -z "${CT_NO_OVERIDE_LC_MESSAGES}" ]; then
2.17 export LC_ALL=C
3.1 --- a/scripts/functions Sun Oct 14 23:46:15 2012 +0000
3.2 +++ b/scripts/functions Sat Oct 06 23:48:07 2012 +0200
3.3 @@ -5,6 +5,8 @@
3.4 # Prepare the fault handler
3.5 CT_OnError() {
3.6 local ret=$?
3.7 + local result
3.8 + local old_trap
3.9 local intro
3.10 local file line func
3.11 local step step_depth
3.12 @@ -35,6 +37,62 @@
3.13 CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
3.14 intro=" called from"
3.15 done
3.16 +
3.17 + # If the user asked for interactive debugging, dump him/her to a shell
3.18 + if [ "${CT_DEBUG_INTERACTIVE}" = "y" ]; then
3.19 + # We do not want this sub-shell exit status to be caught, because
3.20 + # it is absolutely legit that it exits with non-zero.
3.21 + # Save the trap handler to restore it after our debug-shell
3.22 + old_trap="$(trap -p ERR)"
3.23 + trap -- ERR
3.24 + (
3.25 + exec >&6
3.26 + printf "\r \n\nCurrent command"
3.27 + if [ -n "${cur_cmd}" ]; then
3.28 + printf ":\n %s\n" "${cur_cmd}"
3.29 + else
3.30 + printf " (unknown), "
3.31 + fi
3.32 + printf "exited with error code: %d\n" ${ret}
3.33 + printf "Please fix it up and finish by exiting the shell with one of these values:\n"
3.34 + printf " 1 fixed, continue with next build command\n"
3.35 + if [ -n "${cur_cmd}" ]; then
3.36 + printf " 2 repeat this build command\n"
3.37 + fi
3.38 + printf " 3 abort build\n\n"
3.39 + while true; do
3.40 + ${bash} --rcfile <(printf "PS1='ct-ng:\w> '\nPROMPT_COMMAND=''\n") -i
3.41 + result=$?
3.42 + case $result in
3.43 + 1) printf "\nContinuing past the failed command.\n\n"
3.44 + break
3.45 + ;;
3.46 + 2) if [ -n "${cur_cmd}" ]; then
3.47 + printf "\nRe-trying last command.\n\n"
3.48 + break
3.49 + fi
3.50 + ;;&
3.51 + 3) break;;
3.52 + *) printf "\nPlease exit with one of these values:\n"
3.53 + printf " 1 fixed, continue with next build command\n"
3.54 + if [ -n "${cur_cmd}" ]; then
3.55 + printf " 2 repeat this build command\n"
3.56 + fi
3.57 + printf " 3 abort build\n"
3.58 + ;;
3.59 + esac
3.60 + done
3.61 + exit $result
3.62 + )
3.63 + result=$?
3.64 + # Restore the trap handler
3.65 + eval "${old_trap}"
3.66 + case "${result}" in
3.67 + 1) rm -f "${CT_WORK_DIR}/backtrace"; return;;
3.68 + 2) rm -f "${CT_WORK_DIR}/backtrace"; touch "${CT_BUILD_DIR}/repeat"; return;;
3.69 + # 3 is an abort, continue...
3.70 + esac
3.71 + fi
3.72 fi
3.73
3.74 # And finally, in top-level shell, print some hints
3.75 @@ -157,10 +215,11 @@
3.76 # Usage: CT_DoExecLog <level> [VAR=val...] <command> [parameters...]
3.77 CT_DoExecLog() {
3.78 local level="$1"
3.79 + local cur_cmd
3.80 shift
3.81 (
3.82 for i in "$@"; do
3.83 - tmp_log+="'${i}' "
3.84 + cur_cmd+="'${i}' "
3.85 done
3.86 while true; do
3.87 case "${1}" in
3.88 @@ -168,8 +227,39 @@
3.89 *) break;;
3.90 esac
3.91 done
3.92 - CT_DoLog DEBUG "==> Executing: ${tmp_log}"
3.93 - "${@}" 2>&1 |CT_DoLog "${level}"
3.94 + # This while-loop goes hand-in-hand with the ERR trap handler:
3.95 + # - if the command terminates successfully, then we hit the break
3.96 + # statement, and we exit the loop
3.97 + # - if the command terminates in error, then the ERR handler kicks
3.98 + # in, then:
3.99 + # - if the user did *not* ask for interactive debugging, the ERR
3.100 + # handler exits, and we hit the end of the sub-shell
3.101 + # - if the user did ask for interactive debugging, the ERR handler
3.102 + # spawns a shell. Upon termination of this shell, the ERR handler
3.103 + # examines the exit status of the shell:
3.104 + # - if 1, the ERR handler returns; then we hit the else statement,
3.105 + # then the break, and we exit the 'while' loop, to continue the
3.106 + # build;
3.107 + # - if 2, the ERR handler touches the repeat file, and returns;
3.108 + # then we hit the if statement, and we loop for one more
3.109 + # iteration;
3.110 + # - if 3, the ERR handler exits with the command's exit status,
3.111 + # and we're dead;
3.112 + # - for any other exit status of the shell, the ERR handler
3.113 + # prints an informational message, and respawns the shell
3.114 + #
3.115 + # This allows a user to get an interactive shell that has the same
3.116 + # environment (PATH and so on) that the failed command was ran with.
3.117 + while true; do
3.118 + rm -f "${CT_BUILD_DIR}/repeat"
3.119 + CT_DoLog DEBUG "==> Executing: ${cur_cmd}"
3.120 + "${@}" 2>&1 |CT_DoLog "${level}"
3.121 + if [ -f "${CT_BUILD_DIR}/repeat" ]; then
3.122 + continue
3.123 + else
3.124 + break
3.125 + fi
3.126 + done
3.127 )
3.128 # Catch failure of the sub-shell
3.129 [ $? -eq 0 ]