Re: [v2 PATCH] eval: Only restore exit status on exit/return

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

 



On 14/12/2018 08:02, Harald van Dijk wrote:
On 14/12/2018 03:10, Herbert Xu wrote:
On Sat, Dec 08, 2018 at 03:45:11PM +0000, Harald van Dijk wrote:

--- a/src/eval.c
+++ b/src/eval.c
@@ -116,10 +116,7 @@ INCLUDE "eval.h"
  EXITRESET {
      evalskip = 0;
      loopnest = 0;
-    if (savestatus >= 0) {
-        exitstatus = savestatus;
-        savestatus = -1;
-    }
+    savestatus = -1;
  }
  #endif

The reason this is needed is to support a naked return.  With
your patch a naked return would either have to always return the
saved status or the new status.  Neither of which is what we
want.

I actually saw the commit you referenced already and tested that with my patch before sending. This is how I tested it:

Returns 1:

   f() {
     false; return
   }
   f

Returns 0:

   f() {
     trap "false; return" USR1
     kill -USR1 $$
   }
   f

The former picks up the status of the false command, the latter of the kill command. This works because although returncmd() only looks at exitstatus, so returns the wrong value, in the no-argument version it sets skip to SKIPFUNCDEF, causing dotrap() to restore the original exitstatus value, whereas in the version that does take arguments, skip is set to SKIPFUNC, causing dotrap() to leave exitstatus alone.

Which is exactly how that particular commit was supposed to work in the first place, so perhaps it's simpler to put it as "in these tests, changes to exitreset() do not cause the test to break because exitreset() is never called at the wrong time".

If there's some test that breaks, it would need to be one where the original exitstatus needs to be restored by exitreset(), *and* the original exitstatus is not already restored by dotrap().

The original exitstatus is not restored by dotrap() only if evalskip == SKIPFUNC (i.e. return with argument), in which case it shouldn't be restored, or it exits with an exception. And exitreset() is only called when control gets back to main() via an exception.

So you'd need an example where an exception is raised after the return command successfully completes without arguments, yet before the function the return command is in (if any) actually returns, where that exception would then reach main(). I struggle to come up with such an example.



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

  Powered by Linux