bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ERR trap reset in subshell by unrelated trap


From: Jan Klötzke
Subject: ERR trap reset in subshell by unrelated trap
Date: Thu, 18 Feb 2016 22:12:22 +0100
User-agent: Mutt/1.5.23 (2014-03-12)

Configuration Information [Automatically generated, do not change]:
Machine: i586
OS: linux-gnu
Compiler: gcc 
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i586' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i586-pc-linux-gnu' -DCONF_
uname output: Linux debian 4.1.0 #1 SMP Sat Jul 11 10:34:14 CEST 2015 i686 
GNU/Linux
Machine Type: i586-pc-linux-gnu
 
Bash Version: 4.3 
Patch Level: 30
Release Status: release
  
Description:

Setting the errtrace shell option makes subshells inherit the ERR trap
of the parent. This is working fine but the ERR trap is silently reset
in the subshell when another, unrelated signal trap is installed.

Repeat-By:

Execute the following script. The execution should stop in the shell
function at the 'false' command due to the ERR trap and the errtrace
option.

$ cat > test.sh <<'EOF'
#!/bin/bash

set -o errtrace
trap 'echo "ERR trap called at level $BASH_SUBSHELL" ; exit 1' ERR

(
        echo "Subshell inherited traps:"
        trap

        # install unrelated EXIT trap
        trap 'echo "Subshell EXIT trap called: $?"' EXIT

        echo "Traps after installing additional EXIT trap:"
        trap

        # should fail but doesn't
        false
        echo "SHOULD NOT BE REACHED"
)

echo "SHOULD NOT BE REACHED EITHER"
EOF

$ bash ./test.sh
Subshell inherited traps:
trap -- 'echo "ERR trap called at level $BASH_SUBSHELL" ; exit 1' ERR
Traps after installing additional EXIT trap:
trap -- 'echo "Subshell EXIT trap called: $?"' EXIT
SHOULD NOT BE REACHED
Subshell EXIT trap called: 0
SHOULD NOT BE REACHED EITHER

This bug is still present in the latest version:

$ ./bash --version
GNU bash, version 4.4.0(4)-beta (i686-pc-linux-gnu)

Fix:

The culprit seems to be free_trap_strings(). This function is invoked in
a subshell to cleanup allocated strings. *But* it purges the shell
special traps (DEBUG, ERR, RETURN) too, even though they were left in
place by reset_or_restore_signal_handlers() if the right options were
set.

The following patch fixes the problem but I'm not sure if this is
correct. At least the test case is working then as expected:

$ ./bash ./test.sh
Subshell inherited traps:
trap -- 'echo "ERR trap called at level $BASH_SUBSHELL" ; exit 1' ERR
Traps after installing additional EXIT trap:
trap -- 'echo "Subshell EXIT trap called: $?"' EXIT
trap -- 'echo "ERR trap called at level $BASH_SUBSHELL" ; exit 1' ERR
ERR trap called at level 1
Subshell EXIT trap called: 1
ERR trap called at level 0


Regards,
Jan


--- trap.c.orig 2015-09-26 16:39:31.000000000 +0200
+++ trap.c      2016-02-18 21:30:01.116852477 +0100
@@ -1140,12 +1140,31 @@
 {
   register int i;
 
-  for (i = 0; i < BASH_NSIG; i++)
+  for (i = 0; i < NSIG; i++)
     {
       if (trap_list[i] != (char *)IGNORE_SIG)
        free_trap_string (i);
     }
-  trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = 
trap_list[RETURN_TRAP] = (char *)NULL;
+
+  if (trap_list[EXIT_TRAP])
+    free_trap_string (EXIT_TRAP);
+  trap_list[EXIT_TRAP] = (char *)NULL;
+
+  if (function_trace_mode == 0)
+    {
+      if (trap_list[DEBUG_TRAP])
+       free_trap_string (DEBUG_TRAP);
+      if (trap_list[RETURN_TRAP])
+       free_trap_string (RETURN_TRAP);
+      trap_list[DEBUG_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
+    }
+
+  if (error_trace_mode == 0)
+    {
+      if (trap_list[ERROR_TRAP])
+       free_trap_string (ERROR_TRAP);
+      trap_list[ERROR_TRAP] = (char *)NULL;
+    }
 }
 
 /* Free a trap command string associated with SIG without changing signal



reply via email to

[Prev in Thread] Current Thread [Next in Thread]