2

Below is a example BASH script.

#!/bin/bash

exithdl() { 
    echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}

trap exithdl EXIT

fun() {
    echo "in fun subshell=$BASH_SUBSHELL" >&2
    trap -p EXIT >&2
    echo "returned from fun"
}

echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2

When executed the following output is produced.

subshell=0
trap -- 'exithdl' EXIT
in fun subshell=1
trap -- 'exithdl' EXIT
returned from fun
exiting
in exithdl subshell=0

The trap -p EXIT >&2 command in subshells 0 and 1 shows a EXIT trap defined, but the exithdl function only executes after subshell 0 exits. If there a way to determine that exithdl will not execute after subshell 1 exits? In other words, is there a command or commands that I could add to fun so this function could determine that subshell 1 does not have a EXIT trap?

In the example, an EXIT trap is defined for subshell 0, but not for subshell 1. The trap -p EXIT command shows the exact same output when executed in both subshells. So, I have assumed trap -p EXIT can not be used to check if a trap exists for a particular subshell. I acknowledge that the trap -p EXIT command shows the existence of an EXIT trap when executed in fun, but not if the EXIT trap will execute when fun returns. Am I missing something?

1

1 Answer 1

1

When Using Bash 3

The answer depends on the version of bash you are using. For example, my Mac, with macOS High Sierra installed, by default uses GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17). In this case, the problem can be fixed by added parentheses to the command trap -p EXIT >&2 in function fun, as shown below.

#!/bin/bash

exithdl() { 
    echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}

trap exithdl EXIT

fun() {
    echo "in fun subshell=$BASH_SUBSHELL" >&2
    (trap -p EXIT >&2) # <--- See Here
    echo "returned from fun"
}

echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2

The resulting output, shown below, no longer shows function fun as having a EXIT trap.

subshell=0
trap -- 'exithdl' EXIT
in fun subshell=1
returned from fun
exiting
in exithdl subshell=0

This method also works for a subset of the other traps. For example, this subset includes the INT, QUIT, TERM and CHLD traps. However, this subset does not include HUP and other traps.

When Using Bash 4 and 5

I also have Ubuntu 18 and 19 installed in VirtualBox. These operating systems by default are using GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu) and GNU bash, version 5.0.11(1)-release (x86_64-pc-linux-gnu), respectively. When the script with the change shown above executes, the result is unchanged from the original output. However, for these newer versions of bash, the problem can be fixed by added a trap command before the command trap -p EXIT >&2 in function fun, as shown below.

#!/bin/bash

exithdl() { 
    echo "in exithdl subshell=$BASH_SUBSHELL" >&2
}

trap exithdl EXIT

fun() {
    echo "in fun subshell=$BASH_SUBSHELL" >&2
    trap -- KILL # <--- See Here
    trap -p EXIT >&2
    echo "returned from fun"
}

echo "subshell=$BASH_SUBSHELL" >&2
trap -p EXIT >&2
echo "$(fun)" >&2
echo "exiting" >&2

The trap -- KILL command was chosen because the KILL trap can not be changed. This results in the same output as shown above. This method also works for the other traps.

Conclusion

If you want to set a variable (say exitTrap) to the command used to define the current EXIT trap, then use the script shown below. This should work for bash 3, 4 and 5.

trap -- KILL
exitTrap="$( (trap -p EXIT) )"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .