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:
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:
1 #!/bin/bash
2 shopt -s extdebug
3 main() {
4 trap 'echo $LINENO' ERR
5 (exit 17)
6 }
7 main
The above has the output of 3
.
Next, consider changing $(...)
to `...`
:
1 #!/bin/bash
2 shopt -s extdebug
3 main() {
4 trap 'echo $LINENO' ERR
5 `exit 17`
6 }
7 main
The above has the output of 5
.
Now, I did my own test:
1 #!/bin/bash
2 shopt -s extdebug
3 main() {
4 trap 'echo $LINENO' ERR
5 $(exit 17)
6 }
7 main
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With