Linux-Dash Archive mirror
 help / color / mirror / Atom feed
From: Dirk Fieldhouse <fieldhouse@gmx.net>
To: DASH mailing list <dash@vger.kernel.org>
Subject: 'return' from subshell in function doesn't
Date: Sun, 8 Mar 2020 12:35:17 +0000	[thread overview]
Message-ID: <9b3a55fb-df00-8ac3-7a1e-b60e24aa2970@gmx.net> (raw)
In-Reply-To: <S1726267AbgCHLof/20200308114435Z+1505@vger.kernel.org>

POSIX
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#return>
says, and has since at least 2004:
"The return utility shall cause the shell to stop executing the current
function or dot script. If the shell is not currently executing a
function or dot script, the results are unspecified."

Clear enough, one would think, but consider this example:

foo() {
  echo "$1" |
    while read -r xx _; do
      if [ "$xx" = fum ]; then
        echo EQ
        return 0
      fi
    done
  echo NE
  return 1
}

According to the spec we expect:

$ foo fum || echo WTF
EQ
$

What actually happens, with DASH-0.5.8-2.1ubuntu2 and -0.5.9.1 built
from source:

$ foo fum || echo WTF
EQ
NE
WTF
$ foo baz || echo OK
NE
OK
$

Same with bash-4.3-14ubuntu1.4, busybox-static-1:1.22.0-15ubuntu1.4.

A simpler test case shows that the issue is 'return' not breaking out of
a subshell:

bar() {
( if [ "$1" = fum ]; then
        echo EQ
        return 0
      fi )
  echo NE
  return 1
}

barbar() {
  if [ "$1" = fum ]; then
    echo EQ
    return 0
  fi
  echo NE
  return 1
}

$ bar fum || echo WTF
EQ
NE
WTF
$ bar baz || echo OK
NE
OK
$ barbar fum || echo WTF
EQ
$

As POSIX refers to subshells explicitly elsewhere (eg 'exit') it's
difficult to believe that "subshell" was accidentally omitted from the
list of contexts that 'return' should return from, but implementation
behaviours consistently contradict the spec as written. Can they be made
conformant without breaking existing scripts?

A work-around is to make any subshell explicit and 'exit' from it:

foo_wa() {
  echo "$1" |
    ( while read -r xx _; do
      if [ "$xx" = fum ]; then
        echo EQ
        exit 0
      fi
    done; exit 1 ) && return
  ret=$?
  echo NE
  return $ret
}

$ foo_wa fum || echo WTF
EQ
$


--
London SW6
UK

       reply	other threads:[~2020-03-08 12:35 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <S1726267AbgCHLof/20200308114435Z+1505@vger.kernel.org>
2020-03-08 12:35 ` Dirk Fieldhouse [this message]
2020-03-08 13:44   ` 'return' from subshell in function doesn't Harald van Dijk
2020-03-08 14:40     ` Dirk Fieldhouse
2020-03-08 15:19       ` Harald van Dijk
2020-03-09  7:44         ` Stephane Chazelas
2020-03-09 12:43         ` Dirk Fieldhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9b3a55fb-df00-8ac3-7a1e-b60e24aa2970@gmx.net \
    --to=fieldhouse@gmx.net \
    --cc=dash@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).