2

Background

Execute the following code in bash 3, 4 and 5 respectively, and you will get differing results.

(function handle_error () { echo ERROR; }; trap handle_error ERR; (exit 1))

Imagine that (exit 1) is a command you call which might fail. In this case it always fails, but that doesn't really matter. You would like handle_error to be called when it exits with a non-zero exit code. According to the manual, this is exactly what trap handle_error ERR should do.

Problem

I have a local system with a version of bash 3, and a remote system with a completely different operating system with a version of bash 4.

  • bash 3.2.57(1), 3.2.48(1): Returns no output. Excerpt from man bash for the trap builtin:

    If a sigspec is ERR, the command arg is executed whenever a simple command has a non-zero exit status, subject to the following conditions...

  • bash 4.4.23(1), 4.4.12(1): prints ERROR as expected. Excerpt from man bash for the trap builtin:

    If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status, subject to the following conditions...

  • bash 5.0.2(1): prints ERROR as expected.

The documentation leads me to think that the behaviour should be the same over both versions, but it isn't.

I logged onto #bash on Freenode, and verified there as well that this behaviour differs in the same way over all major versions 3, 4 and 5 with their shell bot (nick shbot), which allows you to specify the major version. This shell bot happens to run on a different operating system to both systems which I have tried it on, with differing minor versions over the same major versions of bash which I have access to.

Question

Could anyone point to an authoritative source which explains why this behaviour differs over versions 3, 4 and 5 of bash? I find it hard to believe this this is a bug. There must be another reason which I am missing.

  • Hmm... Testing this in Bash 5.0 shows that it prints ERROR. Setting BASH_COMPAT to e.g. 3.2 does not change this, so it must (?) be related to a fixed bug or similar, in-between release 3 and 4 somewhere. Do you have more exact release numbers than just 3 and 4? – Kusalananda Feb 19 at 17:34
  • I've updated the question with the exact versions, and I've tested on version 5 as well now. – justinpc Feb 19 at 17:51
2

That looks like a bug in Bash 3.2.

I can't find an entry in the changelog that would directly match that. There's only a vague mention about changing the behavior of the errexit option to match POSIX consensus (item l in the change from bash-4.0-rc1 to bash-4.0-release).

That may be related, as there's a similar issue with errexit, this doesn't trigger it in Bash 3.2, but does in Bash 4.0 (it should print nothing, since the shell should exit when the subshell command fails):

$ ./bash3.2 -c 'set -e; (exit 1); echo end.'
end.

Note that the issue here seems to be the subshell, as this works in both versions:

$ ./bash3.2 -c 'trap "echo ERROR" ERR; false'
ERROR
  • Interesting to see the subshell aspect. I wondered whether the subshell was resetting the traps on return, but (trap "echo ERROR" ERR; (exit 1); trap -p) returns trap -- 'echo ERROR' ERR on bash 3.2.48. – justinpc Feb 19 at 18:48
  • What about "b. Fixed a bug that caused subshells to free trap strings associated with inherited signals." in bash-4.4-rc1 to bash-4.4-beta2? The trap still seems to be around though. – justinpc Feb 19 at 18:54
  • @justinpc, I tried with 3.2.57(1)-release and 4.0.0(1)-release, so a change in 4.4 is too late – ilkkachu Feb 19 at 19:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.