From patchwork Mon Oct 15 21:45:13 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Yann E. MORIN" X-Patchwork-Id: 191668 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 5B5D82C00A5 for ; Tue, 16 Oct 2012 08:45:52 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=sourceware.org; s=default; x=1350942352; h=Comment: DomainKey-Signature:Received:Received:Received:Received: Content-Type:MIME-Version:Content-Transfer-Encoding:Subject: Message-Id:In-Reply-To:References:User-Agent:Date:From:To:Cc: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Subscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=6r8vy8U QZPhPLHfcqvnVJ0QNFsA=; b=XUYgLWN+f73hYdsNxePE+iVZC+o2IfHFNkPyCH7 b4Kv/HntE/eaALlgOvfI7YUQZ2Cfz0B/FnuN2DWqw0/eXzGDoVcorndwBWWO8+tZ j/XSbWnYj99w6VU08lQNU/qrvWr8SoLe/s2z3b6RqJd3In5NE61bc/pRiLDI+wW9 o4Fg= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=sourceware.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Content-Type:MIME-Version:Content-Transfer-Encoding:Subject:X-Mercurial-Node:Message-Id:In-Reply-To:References:User-Agent:Date:From:To:Cc:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Subscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=gRtNuBpvJ5Mzaqc7MuEGP0zJa9bNnsWsijZnGu/l9nhfGONSUGuMbDMuFvYChq /FMeqVM0DHttgIuGWvjC7vHVqNQkmSJf7xWjCpCrZQ04H4+97NpHyX6r0UwCCpyy 8S1/cqJUWKQl5w+z0GsA1J7dE4Py+LS8VXQlHLo8bMm8o=; Received: (qmail 6129 invoked by alias); 15 Oct 2012 21:45:43 -0000 Received: (qmail 6113 invoked by uid 22791); 15 Oct 2012 21:45:42 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL, BAYES_00, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, KHOP_THREADED, RCVD_IN_DNSWL_NONE, RCVD_IN_HOSTKARMA_YE X-Spam-Check-By: sourceware.org Received: from smtp04.smtpout.orange.fr (HELO smtp.smtpout.orange.fr) (80.12.242.126) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 15 Oct 2012 21:45:38 +0000 Received: from treguer.bzh.lan ([90.32.124.216]) by mwinf5d07 with ME id BZlb1k00C4gEsci03ZlcRM; Mon, 15 Oct 2012 23:45:36 +0200 MIME-Version: 1.0 Subject: [PATCH 1 of 1] scripts: add option to start an interactive debug shell X-Mercurial-Node: de0568d968da614fe8f7287dbd4d65e51b6096e2 Message-Id: In-Reply-To: References: User-Agent: Mercurial-patchbomb/2.0 Date: Mon, 15 Oct 2012 23:45:13 +0200 From: "Yann E. MORIN" To: crossgcc@sourceware.org Cc: Johannes Stezenbach X-IsSubscribed: yes Mailing-List: contact crossgcc-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: crossgcc-owner@sourceware.org Delivered-To: mailing list crossgcc@sourceware.org # HG changeset patch # User "Yann E. MORIN" # Date 1349560087 -7200 # Node ID de0568d968da614fe8f7287dbd4d65e51b6096e2 # 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, 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 http://sourceware.org/ml/crossgcc/2012-09/msg00144.html Signed-off-by: Johannes Stezenbach [yann.morin.1998@free.fr: integrate in the fault handler] Signed-off-by: "Yann E. MORIN" Patchwork-Id: 191571 Patchwork-Id: 191657 --- For unsubscribe information see http://sourceware.org/lists.html#faq 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,23 @@ 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 diff --git a/scripts/functions b/scripts/functions --- a/scripts/functions +++ b/scripts/functions @@ -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_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_BUILD_DIR}/backtrace"; return;; + 2) rm -f "${CT_BUILD_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 @@ # Usage: CT_DoExecLog [VAR=val...] [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 @@ *) 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 ]