[PATCH 1 of 1] scripts: add option to start an interactive debug shell
Yann E. MORIN
yann.morin.1998@free.fr
Mon Oct 15 19:56:00 GMT 2012
# HG changeset patch
# User "Yann E. MORIN" <yann.morin.1998@free.fr>
# Date 1349560087 -7200
# Node ID 82c19a72f25a7b399f6be4e2c8c1cecc45d8c171
# Parent 2a616dab6531ad82876c3252cd2e1cb873375c3f
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, continue, or aborts
at user's whim.
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: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Johannes Stezenbach <js@sig21.net>
diff --git a/config/global/ct-behave.in b/config/global/ct-behave.in
--- a/config/global/ct-behave.in
+++ b/config/global/ct-behave.in
@@ -87,4 +87,22 @@
Say N, please.
+config DEBUG_INTERACTIVE
+ bool
+ prompt "Interactive shell on failed commands"
+ depends on EXPERIMENTAL
+ help
+ If you say 'y' here, then an interactive shell will be spawned for
+ each failed command run via CT_DoExecLog.
+
+ 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
+
endif
diff --git a/scripts/functions b/scripts/functions
--- a/scripts/functions
+++ b/scripts/functions
@@ -5,10 +5,45 @@
# Prepare the fault handler
CT_OnError() {
local ret=$?
+ local old_trap result
local intro
local file line func
local step step_depth
+ # 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
+ old_trap="$(trap -p ERR)"
+ trap ERR
+ (
+ exec >&6
+ printf "Current command\n %s\n" "${cur_cmd}"
+ printf "exited with error code: %d\n" ${ret}
+ printf "Please fix it up and finish by exiting the shell.\n"
+ while true; do
+ bash --rcfile <(echo "PS1='ct-ng:\w> '") -i
+ result=$?
+ case $result in
+ 1) break;;
+ 2) break;;
+ 3) break;;
+ *) echo "please exit with one of these values:"
+ echo "1 fixed, continue with next build command"
+ echo "2 repeat this build command"
+ echo "3 abort build"
+ ;;
+ esac
+ done
+ exit $result
+ )
+ result=$?
+ case "${result}" in
+ 1) return;;
+ 2) touch "${CT_BUILD_DIR}/repeat"; return;;
+ # 3 is an abort, continue...
+ esac
+ fi
+
# To avoid printing the backtace for each sub-shell
# up to the top-level, just remember we've dumped it
if [ ! -f "${CT_BUILD_DIR}/backtrace" ]; then
@@ -157,10 +192,11 @@
# 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 +204,39 @@
*) 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 ]
--
For unsubscribe information see http://sourceware.org/lists.html#faq
More information about the crossgcc
mailing list