git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Jeff King <peff@peff.net>
Date
Mar 31, 2020, 09:34 UTC
Message-ID
<20200331093437.GA7274@coredump.intra.peff.net>
In-Reply-To
<nycvar.QRO.7.76.6.2003302027240.46@tvgsbejvaqbjf.bet>
On Mon, Mar 30, 2020 at 08:39:08PM +0200, Johannes Schindelin wrote:
Show 11 quoted lines
> > 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
Previous: Johannes SchindelinNext: Johannes Schindelin via GitGitGadget
Message 39 of 55 in “Enable GPG in the Windows part of the CI/PR builds”
  1. 0/2 Enable GPG in the Windows part of the CI/PR buildsJohannes Schindelin via GitGitGadget, Mar 23, 2020
  2. 2/2 tests(gpg): increase verbosity to allow debuggingJohannes Schindelin via GitGitGadget, Mar 23, 2020
  3. Jeff KingMar 23, 2020
  4. Jeff KingMar 23, 2020
  5. Junio C HamanoMar 23, 2020
  6. Jeff KingMar 23, 2020
  7. Junio C HamanoMar 23, 2020
  8. Jeff KingMar 23, 2020
  9. Johannes SchindelinMar 24, 2020
  10. Jeff KingMar 24, 2020
  11. Johannes SchindelinMar 24, 2020
  12. Jeff KingMar 24, 2020
  13. 1/2 tests(gpg): allow the gpg-agent to start on WindowsJohannes Schindelin via GitGitGadget, Mar 23, 2020
  14. Junio C HamanoMar 23, 2020
  15. Johannes SchindelinMar 24, 2020
  16. Junio C HamanoMar 24, 2020
  17. Johannes SchindelinMar 24, 2020
  18. Junio C HamanoMar 24, 2020
  19. 0/5 Enable GPG in the Windows part of the CI/PR buildsJohannes Schindelin via GitGitGadget, Mar 25, 2020
  20. 1/5 tests(gpg): allow the gpg-agent to start on WindowsJohannes Schindelin via GitGitGadget, Mar 25, 2020
  21. 2/5 t/lib-gpg.sh: stop pretending to be a stand-alone scriptJohannes Schindelin via GitGitGadget, Mar 25, 2020
  22. Jeff KingMar 26, 2020
  23. Johannes SchindelinMar 26, 2020
  24. Junio C HamanoMar 26, 2020
  25. 3/5 tests: turn GPG, GPGSM and RFC1991 into lazy prereqsJohannes Schindelin via GitGitGadget, Mar 25, 2020
  26. Junio C HamanoMar 25, 2020
  27. Jeff KingMar 26, 2020
  28. Johannes SchindelinMar 26, 2020
  29. Jeff KingMar 27, 2020
  30. Junio C HamanoMar 27, 2020
  31. Eric SunshineMar 27, 2020
  32. Junio C HamanoMar 27, 2020
  33. Jeff KingMar 28, 2020
  34. Jeff KingMar 28, 2020
  35. t/README: suggest how to leave test early with failureJunio C Hamano, Mar 28, 2020
  36. Eric SunshineMar 29, 2020
  37. Jeff KingMar 29, 2020
  38. Johannes SchindelinMar 30, 2020
  39. Jeff KingMar 31, 2020
  40. 4/5 tests: do not let lazy prereqs inside `test_expect_*` turn off tracingJohannes Schindelin via GitGitGadget, Mar 25, 2020
  41. Junio C HamanoMar 25, 2020
  42. Johannes SchindelinMar 26, 2020
  43. Jeff KingMar 26, 2020
  44. Johannes SchindelinMar 26, 2020
  45. 5/5 tests: increase the verbosity of the GPG-related prereqsJohannes Schindelin via GitGitGadget, Mar 25, 2020
  46. Jeff KingMar 26, 2020
  47. Johannes SchindelinMar 26, 2020
  48. 0/5 Enable GPG in the Windows part of the CI/PR buildsJohannes Schindelin via GitGitGadget, Mar 26, 2020
  49. 2/5 t/lib-gpg.sh: stop pretending to be a stand-alone scriptJohannes Schindelin via GitGitGadget, Mar 26, 2020
  50. 1/5 tests(gpg): allow the gpg-agent to start on WindowsJohannes Schindelin via GitGitGadget, Mar 26, 2020
  51. 3/5 tests: do not let lazy prereqs inside `test_expect_*` turn off tracingJohannes Schindelin via GitGitGadget, Mar 26, 2020
  52. 4/5 tests: turn GPG, GPGSM and RFC1991 into lazy prereqsJohannes Schindelin via GitGitGadget, Mar 26, 2020
  53. 5/5 tests: increase the verbosity of the GPG-related prereqsJohannes Schindelin via GitGitGadget, Mar 26, 2020
  54. Jeff KingMar 27, 2020
  55. Junio C HamanoMar 27, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.