Re: [PATCH v2 3/5] tests: turn GPG, GPGSM and RFC1991 into lazy prereqs

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

 



On Mon, Mar 30, 2020 at 08:39:08PM +0200, Johannes Schindelin wrote:

> > So my perspective was the opposite of yours: "return" is the officially
> > sanctioned way to exit early from a test snippet, and "exit" only
> > happens to work because of the undocumented fact that lazy prereqs
> > happen in a subshell. But it turns out neither was documented. :)
> 
> Can a subshell inside a function cause a `return` from said function? I
> don't think so, but let's put that to a test:
> [...]
> To me, the fact that that `return` does not return from the function, but
> only exits the subshell, in my mind lends more credence to the idea that
> `exit` is more appropriate in this context than `return`.

Hmm, yeah, I was wrong about it actually returning from the function.
Thanks for demonstrating.  Returning from just the subshell in the case
of lazy_prereq is OK for our purposes, since the exit value of the
subshell is taken as the result of the prereq check (and in turn becomes
the return value of that function anyway).

But it does make more sympathetic to the idea that "exit" is appropriate
here. Especially given the prodding below (which you can skip to the
last paragraph if you're not interested in shell arcana):

> For shiggles, I also added that `$?` because I really, _really_ wanted to
> know whether my reading of GNU Bash's documentation was correct, and it
> appears I was mistaken: apparently `return` used outside a function does
> _not_ cause a non-zero exit code.

I think the issue may be in the definition of "outside a function".

If we really are at the top-level outside of a function, then return
gives a non-zero exit but _doesn't_ return in bash:

  $ bash -c 'return 2; echo inside=$?'; echo outside=$?
  bash: line 0: return: can only `return' from a function or sourced script
  inside=1
  outside=0

So even though we asked to return 2, it gave us a generic "1" return
code and continued executing (and then outside=0 because the echo was
successful).

And that's true even in a subshell (not we moved "outside" into the bash
process so we can see that it keeps going):

  $ bash -c '(return 2; echo inside=$?); echo outside=$?'
  bash: line 0: return: can only `return' from a function or sourced script
  inside=1
  outside=0

But if we actually _are_ inside a function, even inside a subshell, then
return "works", by stopping execution in the subshell and returning the
value we asked (in your example we got "0" because you didn't specify a
value for "return", so it just propagated the exit code of the earlier
"echo").

  $ bash -c 'f() { (return 2; echo inside=$?); echo outside=$?; }; f'
  outside=2

It's just a bit odd (to me) that it still runs the rest of the function.

Dash behaves a bit more sensibly with an out-of-function return, just
returning from the script:

  $ dash -c 'return 2; echo inside=$?'; echo outside=$?
  outside=2

and with a subshell, it returns only from that subshell:

  $ dash -c '(return 2; echo inside=$?); echo outside=$?'
  outside=2

So inside a subshell-in-a-function, it behaves exactly the same
(returning from the subshell but not the function).

I think the behavior of both shells is fine for our purposes. We _are_
in a function, so as long as we return from the subshell immediately
we're happy. But given the oddities in how bash behaves, and the fact
that POSIX says:

  If the shell is not currently executing a function or dot script, the
  results are unspecified.

it may be better to stay away from the question entirely.

-Peff



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux