On 22/08/2021 00:31, Roberto A. Foglietta wrote:
Il giorno sab 21 ago 2021 alle ore 23:33 Harald van Dijk <har...@gigawatt.nl <mailto:har...@gigawatt.nl>> ha scritto:

    Hi again,

    Another bug: the exit status is not preserved.

    Consider

        busybox ash -c 'trap "echo ERR" ERR; false; echo $?'

    This prints ERR, and then 0, because the echo command completed
    successfully. It is supposed to print ERR, and then 1, because like
    EXIT
    actions, ERR actions are supposed to preserve the exit status of the
    last command before the action was invoked.


Patch 11 and testsuite attached.
In the test suite two cases are evaluated exit status =0 !0

I think that's probably correct but suboptimal. You're saving exitstatus using the savestatus global variable, but in that block, you already know that exitstatus is always going to be equal to the local status variable: the only time that exitstatus != status is if the earlier exitstatus = status; assignment is bypassed, but the only way that can get bypassed is if evaltree(NULL, flags) is called, in which case status will equal 0 so the block never gets entered. You should be able to repeat the earlier exitstatus = status; assignment without saving it in a new variable.

    I am also somewhat concerned that there may be cases where the global
    variables "doingtrap" and "recursive" are set, but evalstring() exits
    via raise_exception() and they are never cleared, preventing future ERR
    handlers from running. I do not currently have a test case where it
    matters, but am not convinced there are no test cases where it matters.


line 13.320 in evalstring

exception_handler = savehandler;
if (ex)
longjmp(exception_handler->loc, ex);

do you think that this might resolve the issue?

exception_handler = savehandler;
if (ex) {
doingtrap = 0; recursive = 0;
longjmp(exception_handler->loc, ex);
}

I don't think that's right. evalstring() may end up calling evalstring() again recursively, and in that case you wouldn't want to clear doingtrap or recursive.

Obviously recursive should become a global variable.
When an exception is raised, what is going to happen? Exit?
In case of exit then it is not a problem, IMHO.

That's why I haven't been able to create a test case yet where it goes wrong: in *almost* all cases where an exception is raised, the shell will terminate. The shell won't immediately terminate, EXIT handlers run first, but if that runs in the context of an ERR handler, leaving doingtrap and recursive alone is the right thing to do, as ERR handlers shouldn't run again.

But only almost all cases, not all cases. One exception, and I am not sure if it is the only one, is that the 'command' builtin can catch and handle exceptions that come from errors raised by special built-ins. Normally they cause the shell to terminate, but the 'command' built-in makes such errors non-fatal.

If it is possible for a special built-in within an ERR handler to raise an exception, and for that exception to be caught and handled by an outer 'command' builtin, it should be possible to run more ERR handlers after that.

Thank you, -R
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to