For the Bash program:
1 #!/bin/bash
2
3 trapinfo()
4 {
5 echo "=== Trap Info: Status=$? LINENO=$@ A=$A"
6 }
7
8 main()
9 {
10 trap 'trapinfo $LINENO -- ${BASH_LINENO[*]}' ERR
11
12 set -e
13 set -E
14 set -o errtrace
15 shopt -s extdebug
16
17 local -g A=1
18
19 # false # If uncommented, LINENO would be 19
20 (exit 73) # LINENO is 9. How can I get 20 instead?
21
22 A=2
23 }
24
25 main
with the output:
=== Trap Info: Status=73 LINENO=9 -- 25 0 A=1
I am looking to find a way to have it so that subshells that exit with a non-zero status are caught by trap
and show the line number of the failing subshell. In the example above, I am looking for line 20 as the result. I note that if the error is not in a subshell, I do get the wanted line number (see false
above).
I've tried moving the trap to just before the subshell to check if the line number 9
was actually connected to the trap invocation, but I get the same results. I've also tried placing the set
and shopt
entries into the subshell as well--again with no change in behavior.
Environment:
- bash-4.2.46-21.el7_3.x86_64: this is a requirement, but POSIX compliance is NOT required. I am also interested in later Bash releases (4.2+).
- CentOS 7+: while mainly interested in CentOS, I will eventually need this for Bash scripts that are deployed on Ubuntu 16.04+ and CentOS 6 as well.
Is it possible to get the line number of the subprocess that returns the non-zero status? If it is not possible, is there any documentation to that effect? If a solution exists, it should scale well without unnecessary decoration in the code.
I asked the Bash e-mail group help-bash for help on this. Eduardo Bustamante provided the following two code blocks to point to a possible bug in Bash that is at the root of the difficulty here.
First, an even simpler demonstration of the problem:
The above has the output of
3
.Next, consider changing
$(...)
to`...`
:The above has the output of
5
.Now, I did my own test:
This also has the desired output of
5
.So, the resolution of this question seems to be that this is a bug in Bash with the workaround being to use command substitution instead of just a subshell
()
.Again, my thanks to Eduardo Bustamante for his insight. I'll wait a few days to see if he posts a solution here to accept his answer; otherwise, I'll mark this as the accepted answer and give thanks to him.