help-bash
[Top][All Lists]
Advanced

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

Re: Infinite loop with error trap and subshell


From: Samir Aguiar
Subject: Re: Infinite loop with error trap and subshell
Date: Fri, 29 Oct 2021 19:37:15 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0

Sorry about the misleading subject; I had a draft e-mail written when I started digging and at first I thought it was an infinite loop.

As I mentioned in the body of the message, the issue is that an infinite number of processes are spawned. While the script is running, `ps` outputs:

    root@6b2bc60fe1db:~/code/bash# ps -ef
    UID          PID    PPID  C STIME TTY          TIME CMD
    root           1       0  0 19:19 pts/0    00:00:00 bash
    root       62039       1  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62042   62039  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62043   62039  0 22:34 pts/0    00:00:00 cat
    root       62045   62042  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62046   62042  0 22:34 pts/0    00:00:00 cat
    root       62048   62045  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62049   62045  0 22:34 pts/0    00:00:00 cat
    root       62051   62048  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62052   62048  0 22:34 pts/0    00:00:00 cat
    root       62054   62051  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62055   62051  0 22:34 pts/0    00:00:00 cat
    root       62057   62054  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62058   62054  0 22:34 pts/0    00:00:00 cat
    root       62060   62057  0 22:34 pts/0    00:00:00 ./bash sample.sh
    root       62061   62057  0 22:34 pts/0    00:00:00 cat
    root       62063   62060  0 22:34 pts/0    00:00:00 ./bash sample.sh
    ...

Kind regards,
Samir Aguiar

On 29/10/2021 19:29, Samir Aguiar wrote:
Hi,

We have a script that prints the call stack inside an ERR trap. The code invokes the `caller` built-in in a while loop that is piped to another while loop, which uses `read` to parse the output of `caller` and pretty-print it. However, after updating to Bash 5.1 the script now leads to an infinite number of processes being spawn and the error handler being called over and over. Prior to that version this did not happen.

My colleague Philipp Gesang and I have come up with a sample script to reproduce the problem. The ERR trap will create a flag file when it gets called again to indicate that infinite forking *would* occur, in which case it will exit with 99. An exit code of 0 means that nothing wrong would happen. The invocation of `/bin/false` (or similar) inside the while loop is mandatory for the problem to be triggered.

---------------------------
     #/bin/bash
     shopt -s extdebug

     bisect_abort=0
     error_flag_file="triggered_error"
     rm -f "$error_flag_file"

     handle_error()
     {
         [ $bisect_abort -gt 1 ] && touch "$error_flag_file" && return
         bisect_abort=$((bisect_abort+1))

         while :; do
             # need to produce an nonzero return code
             /bin/false
             # only a single iteration is needed
             break
         done | cat
     }

     trap handle_error ERR

     /bin/false

     # error code path reached on bash-5.1.x
     [ -f "$error_flag_file" ] && rm -f "$error_flag_file" && exit 99

     # normal exit path reached on bash-5.0.x
     exit 0
---------------------------

On bash 5.1.8 I get an exit code of 99, but on 5.0 I get 0.

This behavior was introduced in commit 8f576adedb5 (dev branch), more specifically in `execute_cmd.c`:

---------------------------
   -#if 0    /* TAG:bash-5.1 */
   +
     /* We are in a subshell, so forget that we are running a trap handler or
         that the signal handler has changed (we haven't changed it!) */
      if (running_trap > 0)
        {
          run_trap_cleanup (running_trap - 1);
   -      running_trap = 0;
   +      running_trap = 0;        /* XXX - maybe leave this */
        }
---------------------------

We have managed to work around it by changing the first while loop so that it will not produce an error in the last iteration, but I was wondering - is this expected behavior? Should we avoid subshells inside traps?

Thanks in advance.

Kind regards,
Samir Aguiar



reply via email to

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