'return' from subshell in function doesn't

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux