scripts: fix dumping execution backtrace

Dumping the backtrace has been broken since changeset #652e56d6d35a:
    scripts: execute each steps in a subshell

We can spawn sub-sub-shells in some cases.

The way the fault handler works is to dump the backtrace, but to avoid
printing it once for every sub-shell (which could get quite confusing),
it simply exits when it detects that it is being run in a sub-shell,
leaving to the top-level shell the work to dump the backtrace.

Because each step is executed in its own sub-shell, the variable arrays
that contain the step name, the source file and line number, are lost
when exiting the per-step sub-shell.

Hence, the backtrace is currently limited to printing only the top-level
main procedure of the shell.

Fix this thus:
- when dumping the bckatraces for the steps & the functions, remember
  it was dumped, and only dump it if it was not already dumped
- at the top-level shell, print the hints

Also, rename the top-level step label.

Reported-by: Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
(transplanted from 4193d6e6a17430a177fa88c287879c2c35e319f3)
This commit is contained in:
Yann E. MORIN" 2011-12-13 23:32:39 +01:00
parent 3ee64c2768
commit 4235dbd5b8

View File

@ -6,52 +6,52 @@
CT_OnError() {
local ret=$?
local intro
local file
local line
local func
local step_depth
local file line func
local step step_depth
# Bail out early in subshell, the upper level shell will act accordingly.
[ ${BASH_SUBSHELL} -eq 0 ] || exit $ret
# 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
touch "${CT_BUILD_DIR}/backtrace"
# Print steps backtrace
step_depth=${CT_STEP_COUNT}
CT_STEP_COUNT=2
CT_DoLog ERROR ""
intro="Build failed"
for((step=step_depth; step>1; step--)); do
CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
intro=" called"
done
# Print steps backtrace
step_depth=${CT_STEP_COUNT}
CT_STEP_COUNT=1 # To have a zero-indentation
CT_DoLog ERROR ""
CT_DoLog ERROR ">>"
intro="Build failed"
for((step=step_depth; step>0; step--)); do
CT_DoLog ERROR ">> ${intro} in step '${CT_STEP_MESSAGE[${step}]}'"
intro=" called"
done
# Print functions backtrace
intro="Error happened in"
offset=1
CT_DoLog ERROR ">>"
for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
case "${depth}" in
1) line="";;
*) line="@${BASH_LINENO[${depth}-1]}"
esac
func="${FUNCNAME[${depth}]}"
CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
intro=" called from"
done
# Help diagnose the error
CT_DoLog ERROR ">>"
if [ "${CT_LOG_TO_FILE}" = "y" ]; then
CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
# Print functions backtrace
intro="Error happened in"
CT_DoLog ERROR ">>"
for((depth=1; ${BASH_LINENO[$((${depth}-1))]}>0; depth++)); do
file="${BASH_SOURCE[${depth}]#${CT_LIB_DIR}/}"
func="${FUNCNAME[${depth}]}"
line="@${BASH_LINENO[${depth}-1]:-?}"
CT_DoLog ERROR ">> ${intro}: ${func}[${file}${line}]"
intro=" called from"
done
fi
CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
CT_DoLog ERROR ""
CT_DoLog ERROR "Build failed in step '${CT_STEP_MESSAGE[${CT_STEP_COUNT}]}'"
# And finally, in top-level shell, print some hints
if [ ${BASH_SUBSHELL} -eq 0 ]; then
# Help diagnose the error
CT_STEP_COUNT=1 # To have a zero-indentation
CT_DoLog ERROR ">>"
if [ "${CT_LOG_TO_FILE}" = "y" ]; then
CT_DoLog ERROR ">> For more info on this error, look at the file: '${tmp_log_file#${CT_TOP_DIR}/}'"
fi
CT_DoLog ERROR ">> There is a list of known issues, some with workarounds, in:"
CT_DoLog ERROR ">> '${CT_DOC_DIR#${CT_TOP_DIR}/}/B - Known issues.txt'"
CT_DoLog ERROR ""
CT_DoEnd ERROR
CT_DoLog ERROR ""
CT_DoEnd ERROR
rm -f "${CT_BUILD_DIR}/backtrace"
fi
exit $ret
}
@ -288,7 +288,7 @@ CT_DoDate() {
}
CT_STEP_COUNT=1
CT_STEP_MESSAGE[${CT_STEP_COUNT}]="<none>"
CT_STEP_MESSAGE[${CT_STEP_COUNT}]="(top-level)"
# Memorise a step being done so that any error is caught
# Usage: CT_DoStep <loglevel> <message>
CT_DoStep() {