[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Infinite loop with error trap and subshell
From: |
Chet Ramey |
Subject: |
Re: Infinite loop with error trap and subshell |
Date: |
Sat, 30 Oct 2021 16:03:53 -0400 |
User-agent: |
Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.2.1 |
On 10/29/21 6:29 PM, 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.
OK. First, the function inherits the ERR trap because of the `extdebug'
setting. The subshell that's started to run the while loop in the pipeline
inherits the ERR trap from its parent (the shell function) and is where the
ERR trap gets triggered again, and where the `knowledge' that the shell is
running a trap handler is discarded.
There is a discussion about inheriting trap handlers and allowing recursive
trap handler calls at
https://lists.gnu.org/archive/html/bug-bash/2018-04/msg00047.html
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.
The question is whether or not the subshell should `know' that it's
executing as part of a trap handler. The reason it might need to know this,
as you discovered, is so the internal function responsible for running trap
handlers can suppress recursive trap handlers.
A subshell is created as a copy of its parent, including state, though trap
handlers are usually reset to their inherited values (in this case, the
extdebug setting inhibits that resetting for the shell's special signals,
so the subshell keeps the ERR trap).
Should trap handlers be able to run recursively? That is, in an ERR trap
handler (which is a special pseudo-signal), should a failing command cause
the trap handler to run again? This is how other trap handlers behave.
If trap handlers should be allowed to run recursively, should that extend
to the special shell pseudo-signals (ERR/RETURN/DEBUG) or be restricted to
the ones that correspond to actual signals? The shell allows the special
pseudo-signals to run trap handlers recursively.
If you put these things together, you see what happens. The subshell
started to run the forked while loop inherits the ERR trap `forgets' that
it's running a trap handler to allow recursive trap handlers.
So what about this process should be changed?
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU chet@case.edu http://tiswww.cwru.edu/~chet/