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.