Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ERR trap not called when setting readonly variable

Tags:

bash

shell

Script test.sh:

set -euo pipefail

function _trap_ext
{
    echo '_trap_ext'
}
function _trap_error
{
    echo '_trap_error'
}
trap "_trap_ext" EXIT
trap "_trap_error" ERR

readonly foo='bar'
foo='bar'

echo 'foobar'

Output:

./test.sh: line 14: foo: readonly variable
_trap_ext

The script terminates at line 14 because of the error (-e option) but the _trap_error function is not called. Why not?

GNU bash, version 4.1.2(1)-release (x86_64-unknown-linux-gnu), 4.2.45(1)-release (i586-suse-linux-gnu)

like image 306
Toru Avatar asked Mar 30 '15 13:03

Toru


People also ask

How do I get rid of readonly variables?

readonly command makes it final and permanent until the shell process terminates. If you need to change a variable, don't mark it readonly. Show activity on this post. An alternative if gdb is unavailable: You can use the enable command to load a custom builtin that will let you unset the read-only attribute.

What is readonly variable in shell?

Read-only Variables Shell provides a way to mark variables as read-only by using the read-only command. After a variable is marked read-only, its value cannot be changed. For example, the following script generates an error while trying to change the value of NAME − #!/bin/sh NAME="Zara Ali" readonly NAME NAME="Qadiri"

What does set Pipefail do?

If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default. Without pipefail , the return value of a pipeline is the exit status of the last command.

What is bash trap command?

A built-in bash command that is used to execute a command when the shell receives any signal is called `trap`. When any event occurs then bash sends the notification by any signal. Many signals are available in bash. The most common signal of bash is SIGINT (Signal Interrupt).


1 Answers

This sounds like it might be a bug. From the man pages:

-e
Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command (see SHELL above), exits with a non-zero status.
...
A trap on ERR, if set, is executed before the shell exits. This option applies to the shell environment and each subshell environment separately (see COMMAND ENVIRONMENT above), and may cause subshells to exit before executing all the commands in the subshell.

From what the man pages say, it should execute the ERR trap. You can test that it works as expected in other situations by inserting a false before the foo='bar' statement.

It also appears that bash doesn't call the ERR trap on syntax errors either, so it may be that attempting to overwrite a readonly variable falls into a similar category of errors which skip the ERR trap. However, that explanation is pure speculation.

like image 133
Mr. Llama Avatar answered Oct 01 '22 08:10

Mr. Llama