diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-09-07 01:54:23 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-09-07 02:01:03 +0200 |
commit | f415e21a7dce1d4f4b760fddfaba85c551681e11 (patch) | |
tree | 1c126cfd0ff6193b151db4fddaf79fac3d822dfd | |
parent | 41beb53787ec798a27f336c4758cb5ebd8f0c75a (diff) |
ash: eval: Do not cache value of eflag in evaltree
Upsteam commit:
Date: Mon, 17 May 2021 15:19:23 +0800
eval: Do not cache value of eflag in evaltree
Patrick BrĂ¼nn <P.Bruenn@beckhoff.com> wrote:
> Since we are migrating to Debian bullseye, we discovered a new behavior
> with our scripts, which look like this:
>>cleanup() {
>> set +e
>> rmdir ""
>>}
>>set -eu
>>trap 'cleanup' EXIT INT TERM
>>echo 'Hello world!'
>
> With old dash v0.5.10.2 this script would return 0 as we expected it.
> But since commit 62cf6955f8abe875752d7163f6f3adbc7e49ebae it returns
> the last exit code of our cleanup function.
...
Thanks for the report. This is actually a fairly old bug with
set -e that's just been exposed by the exit status change. What's
really happening is that cleanup itself is triggering a set -e
exit incorrectly because evaltree cached the value of eflag prior
to the function call.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 15 | ||||
-rw-r--r-- | shell/ash_test/ash-misc/exitcode_trap7.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-misc/exitcode_trap7.tests | 7 |
3 files changed, 16 insertions, 8 deletions
diff --git a/shell/ash.c b/shell/ash.c index 2d2c09ba5..c65f09782 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9336,8 +9336,7 @@ evaltree(union node *n, int flags) case NCMD: evalfn = evalcommand; checkexit: - if (!(flags & EV_TESTED)) - checkexit = ~0; + checkexit = ~flags & EV_TESTED; goto calleval; case NFOR: evalfn = evalfor; @@ -9359,7 +9358,6 @@ evaltree(union node *n, int flags) case NAND: case NOR: case NSEMI: { - #if NAND + 1 != NOR #error NAND + 1 != NOR #endif @@ -9387,8 +9385,7 @@ evaltree(union node *n, int flags) if (!status) { n = n->nif.ifpart; goto evaln; - } - if (n->nif.elsepart) { + } else if (n->nif.elsepart) { n = n->nif.elsepart; goto evaln; } @@ -9410,7 +9407,7 @@ evaltree(union node *n, int flags) */ dotrap(); - if (checkexit & status) { + if (checkexit && status) { if (trap[NTRAP_ERR] && !in_trap_ERR) { int err; struct jmploc *volatile savehandler = exception_handler; @@ -9434,10 +9431,12 @@ evaltree(union node *n, int flags) exitstatus = savestatus; } if (eflag) - raise_exception(EXEND); + goto exexit; } - if (flags & EV_EXIT) + if (flags & EV_EXIT) { + exexit: raise_exception(EXEND); + } popstackmark(&smark); TRACE(("leaving evaltree (no interrupts)\n")); diff --git a/shell/ash_test/ash-misc/exitcode_trap7.right b/shell/ash_test/ash-misc/exitcode_trap7.right new file mode 100644 index 000000000..07d66e9d9 --- /dev/null +++ b/shell/ash_test/ash-misc/exitcode_trap7.right @@ -0,0 +1,2 @@ +Start +Ok:0 diff --git a/shell/ash_test/ash-misc/exitcode_trap7.tests b/shell/ash_test/ash-misc/exitcode_trap7.tests new file mode 100755 index 000000000..9772a7b8c --- /dev/null +++ b/shell/ash_test/ash-misc/exitcode_trap7.tests @@ -0,0 +1,7 @@ +$THIS_SH -c ' +cleanup() { set +e; false; } +set -eu +trap cleanup EXIT +echo Start +' +echo Ok:$? |