From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.1 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FROM,HTML_MESSAGE,MAILING_LIST_MULTI autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 15075 invoked from network); 13 Nov 2022 13:56:08 -0000 Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368) by inbox.vuxu.org with ESMTPUTF8; 13 Nov 2022 13:56:08 -0000 ARC-Seal: i=1; cv=none; a=rsa-sha256; d=zsh.org; s=rsa-20210803; t=1668347768; b=CXuLS+/Z7+SPFwqWSJbyAltA+V6reuFY191DZlYNPzwcNhJPH+CpI8QeQVi+o+jttZxHzbH3GM nOtD9dsyAcj/I4Ra6T3DmdCjU5kTzhb2Mjx1x2AOKRizYcT0L1KkD2RLiKdYSZ7Xwrzu5QgIWD vfe/0+laylVw0S/47kdw4PJ5oTtQ77ZSliiGm5pOBrWxhUT+uk+e+lOOqXfj5DmOog28HIXnzZ QcIMa/OVxs5QWcKYMPA0CzLsxJW+BNteC2brv4bHtQTwEDOWHTepAm2E3ccgi0bpxF+uUo7Jkd 2YbGF6r9m2/rxVDAZVyfn5fGfV8oiUFiPzTpEHAa7LrvjA==; ARC-Authentication-Results: i=1; zsh.org; iprev=pass (mail-vk1-f174.google.com) smtp.remote-ip=209.85.221.174; dkim=pass header.d=gmail.com header.s=20210112 header.a=rsa-sha256; dmarc=pass header.from=gmail.com; arc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=zsh.org; s=rsa-20210803; t=1668347768; bh=hNoJ83rW2eMpzoB92KsUpSgWHNmODWpng12LAHxfsMY=; h=List-Archive:List-Owner:List-Post:List-Unsubscribe:List-Subscribe:List-Help: List-Id:Sender:Content-Type:Cc:To:Subject:Message-ID:Date:From:In-Reply-To: References:MIME-Version:DKIM-Signature:DKIM-Signature; b=HFlNPeI+57EnHxV3Chf27/TsfgDeEhKnp4FZ/VCFoJk6WfRQFrlzrJ2wmfhss+ibwN3BOQY7on k5SCvncBqV6b1IY3foeIRWAWfjFYruCoaYL7A3x1MNEmyCKJocUgO6DIBkPH/QcMPls/nFRg7Y E+59qiTfM/lcLyS3jach+xz5SmnOdweZPJBhh4pTR1mbD7LZTqSf1Fkghbh+vEtdgHJuBzaUcZ 9+YQrGI4DYfLXT65y1NrfV2cUeOTkDgQWt7CVkLarxuDmzdjf/mcLFdYylENDQPnZxrQxNnMx+ DDUL+7VKc0JiahFzXHWWaYKsCmCY+0/vhv6Fox3/oJUIdA==; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org; s=rsa-20210803; h=List-Archive:List-Owner:List-Post:List-Unsubscribe: List-Subscribe:List-Help:List-Id:Sender:Content-Type:Cc:To:Subject:Message-ID :Date:From:In-Reply-To:References:MIME-Version:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID; bh=gYS9YgkbUGAz/2atOBJaROgyg9fZsSLdv6PHUCeb9ZA=; b=h+LF9LKLRKW0wfUZIZI0UjduSO 8K4BL8ehY17eIVadCAqEjakJkF6PzaOjOimwLU99ffPedMnxnJzKOr8cBfWl1lXP4kZ22f8bqTdPX z7r7XszxCWFDAmXjoyR+oaN+8ioCEW89g6RfDNAd7bN+j6n23vvbgtYv0va8j76Xb90QkTEyTfrUi Wo1naN2o5pI7tR+F3AXNZ1BIkVh9MMfiJ/gpRXF5DLeP/eKoD+xFp3PeQDVW2ggiUy+d1f2C/w+uH FxBfk7w0GhN5Y7WbIPAdL7PkrAAuBAgVd5oze8JGy8bvdlJ67oi+7fR6ZYxN2ETZdJAVfxFGWaQ/t JVIjOmyQ==; Received: by zero.zsh.org with local id 1ouDSx-0006Hw-OB; Sun, 13 Nov 2022 13:56:07 +0000 Authentication-Results: zsh.org; iprev=pass (mail-vk1-f174.google.com) smtp.remote-ip=209.85.221.174; dkim=pass header.d=gmail.com header.s=20210112 header.a=rsa-sha256; dmarc=pass header.from=gmail.com; arc=none Received: from mail-vk1-f174.google.com ([209.85.221.174]:46722) by zero.zsh.org with esmtps (TLS1.3:TLS_AES_128_GCM_SHA256:128) id 1ouDSL-0005vR-7A; Sun, 13 Nov 2022 13:55:30 +0000 Received: by mail-vk1-f174.google.com with SMTP id e2so3781742vkd.13 for ; Sun, 13 Nov 2022 05:55:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=gYS9YgkbUGAz/2atOBJaROgyg9fZsSLdv6PHUCeb9ZA=; b=QeBZsa/9/lqylCyyqJExwZTYjH1Haj43mt41/q+ajyMqObJzGvzJZykeQXgCHhJIt8 dLIDBc9HME7+IngIVVdW3GYQGlyR5n2ExKqYx46+OuLKUS833hDioSR7wfzCpdwWJASr +P0BiYgj/Y7Xr/p8rEDkcl8+4ep3sRF0NWiz/8Bb+/y1SxjeW3+8swi6CJB977pzR7rA 7W4QIHQJQqT0E09nIjZhDOCEi0AfOFLvJls9cKlXoANSxKk0648tcyloiXStC/LF39nv v0IezrYPmyWYGXg8Mhr11sO7vJdAbqZuiSOpAMdOx0OOwf12Wh0R2yUxzooVIwbvrqq8 jICQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=gYS9YgkbUGAz/2atOBJaROgyg9fZsSLdv6PHUCeb9ZA=; b=ehJ3jicje4cDS0VAc0kQ0SC9lxE2NNHK7aD7b/ERHbYLhjFzFpXp8jPqbeOLwKks0L z4dWmsXnuJy0nA27O11XVNIcU5cix9uh0iwrg8ws2AAMp/6ndTKkTtJbKr1Ww2RkWDyR drYO2cnuukBkoCVFM949S1iol8eEseg5R5yEJmpZ11aq2R0avBXUd4s5QKvKzoEaUR3e KTlUfHPoutVkuCXAcdSgirbDjsNmRdA0SlzWKZz/IphG+Qcy2G78IwSO7tquPLYZCxW+ gIKZRth7y7xcCfZ/+/ICdejvuwfx+KqLlCzgPF3g0DaHp/LsSFt2esSaLCaJ44vD0Wj7 xf2g== X-Gm-Message-State: ANoB5pmGyS4S1LY8nHJpZaTTKd/51NxXKPwfiuIeJo4Z8SuYKJ4xWrPs qtO20t7nYVklfqjvdgHG4bVxt3NBiZY//yxtRQRYrEHeSWc= X-Google-Smtp-Source: AA0mqf4Ekz8pa6rkpvORPg74tMxc8VjfA1E83EUXGXidMW+ITP+RXW1g6nA7GZm4RQicinE5RV5WFRtYX+Pl4G0o5Hk= X-Received: by 2002:a05:6122:8c:b0:3ac:fba7:fc83 with SMTP id r12-20020a056122008c00b003acfba7fc83mr4614831vka.23.1668347727358; Sun, 13 Nov 2022 05:55:27 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Philippe Altherr Date: Sun, 13 Nov 2022 14:55:15 +0100 Message-ID: Subject: Re: [PATCH] More ERR_EXIT (was Re: Tests RE behavior of ERR_EXIT) To: Bart Schaefer Cc: zsh-workers@zsh.org Content-Type: multipart/alternative; boundary="000000000000a6af7805ed5a791e" X-Seq: 50951 Archived-At: X-Loop: zsh-workers@zsh.org Errors-To: zsh-workers-owner@zsh.org Precedence: list Precedence: bulk Sender: zsh-workers-request@zsh.org X-no-archive: yes List-Id: List-Help: , List-Subscribe: , List-Unsubscribe: , List-Post: List-Owner: List-Archive: --000000000000a6af7805ed5a791e Content-Type: text/plain; charset="UTF-8" > > You shouldn't even be bothering with 5.8.1, it's been wrong all along; > it blindly never errexits at the end of an if/then/fi. I think that this isn't necessarily wrong. My understanding of the code so far is that the decision to trigger an ERR_EXIT is pushed down the evaluation stack. In "if cmd1; then cmd2; else cmd3; fi", only the evaluations of the (word codes representing the) commands "cmd1", "cmd2", or "cmd3" can ever trigger an ERR_EXIT. The evaluation of the (word codes representing the) if/then/else itself never triggers an ERR_EXIT. In other words only (the word codes representing) "basic commands", like function calls or UNIX commands, can ever trigger an ERR_EXIT. This strategy has the benefit that ERR_EXIT will be triggered exactly at the point where the fatal non-zero exit status was produced. 00 if 01 cmd1 02 then 03 cmd2 04. else 05. cmd3 06 fi In the example above, with the strategy I described, and with the knowledge that the if condition never triggers an ERR_EXIT, it's guaranteed that an ERR_EXIT will only ever be thrown at line 03 or 05. If the triggering of the ERR_EXIT was sometimes delayed and delegated to the if/then/else, then ERR_EXIT could also be triggered at line 02 or 04, or worse at line 01 or 06, which wouldn't let you know whether the non-zero status originated from "cmd2" or from "cmd3". The delayed/delegated triggering looks undesirable because it gives you less information on the origin of the error. My understanding is that it's also never needed. The behavior of ERR_EXIT is controlled by the variables "noerrexit" and "local_noerrexit". My understanding of these variables is the following: - noerrexit: This variable is set to indicate that the triggering of ERR_EXIT must be disabled in the evaluation of any word code from the point where it's set until it's reset. For example it's set here in execif before the evaluation of the condition and reset here , here , here , and here after the evaluation of the condition. I don't really understand why the reseting is so complicated. It's much more straightforward in execwhile ( here ). - local_noerrexit: This variable is set to indicate that the triggering of ERR_EXIT must be disabled in the remainder of the evaluation of the current word code. For example it's set at the end of each compound command, like here . This used to be a plain "this_noerrexit = 1", which I don't think was wrong. I think my patches so far have uncovered a different bug that was > already present but was masked by the foregoing, which is, that > noerrexit is unwound in cases where it should not be. I think this is > happening at lines 1530-1531 of exec.c, right under the comment about > "hairy code near the end of execif()". That's an area I didn't touch, > but I'm pretty sure it's restoring noerrexit to its state before > entering the "if" (oldnoerrexit) when it should be preserving the > state from the "&&" conditional. In 5.8.1 this gets reversed again > via this_noerrexit. I must admit that I don't understand the NOERREXIT_UNTIL_EXEC logic here , nor the complicated resetting logic of noerrexit at the end of execif. I was about to say that this doesn't seem to be the source of the problem because if, while, and for statements all behave the same in Zsh. function fooIf1() { init; cond=true; if $cond; then cond=false; false > ; fi ; } > function fooIf2() { init; cond=true; if $cond; then cond=false; > false && true; fi ; } function fooWhile1() { init; cond=true; while $cond; do cond=false; false > ; done; } > function fooWhile2() { init; cond=true; while $cond; do cond=false; > false && true; done; } function fooFor1() { init; cond=true; for v in x ; do cond=false; false > ; done; } > function fooFor2() { init; cond=true; for v in x ; do cond=false; > false && true; done; } In the examples above fooIf1, fooWhile1, and fooFor1 all work correctly but fooIf2, fooWhile2, and fooFor2 fail to trigger ERR_EXIT in Zsh 5.8 and trigger it too early (in foo instead of in bar) in Zsh 5.9. However, if I comment out the NOERREXIT_UNTIL_EXEC logic in exec.c (or remove the negation), then fooIf2 and surprisingly also fooFor2 work correctly in Zsh 5.9 but not fooWhile2!?! fooWhile2 still triggers too early. So it looks like this may indeed be the start of the answer. But I'm still scratching my head on why that is. Philippe --000000000000a6af7805ed5a791e Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
You shou= ldn't even be bothering with 5.8.1, it's been wrong all along;
i= t blindly never errexits at the end of an if/then/fi.

=
I think that this isn't necessarily wrong. My understanding = of the code so far is that the decision to trigger an ERR_EXIT is pushed do= wn the evaluation stack. In "if cmd1; then cmd2; else cmd3; fi", = only the evaluations of the (word codes representing the) commands "cm= d1", "cmd2", or "cmd3" can ever trigger an ERR_EXI= T. The evaluation of the (word codes representing the) if/then/else itself = never triggers an ERR_EXIT. In other words only (the word codes representin= g) "basic commands", like function calls or UNIX commands, can ev= er trigger an ERR_EXIT. This strategy has the benefit that ERR_EXIT will be= triggered exactly at the point where the fatal non-zero exit status was pr= oduced.

00 if
01=C2=A0 =C2=A0cmd1
<= div>02=C2=A0 then
03=C2=A0 =C2=A0cmd2
04. else
05.=C2=A0 =C2=A0cmd3
06 fi

In the exam= ple above, with the strategy=C2=A0I described, and with the knowledge that = the if condition never triggers an ERR_EXIT, it's guaranteed that an ER= R_EXIT will only ever be thrown at line 03 or 05. If the triggering of the = ERR_EXIT was sometimes delayed and delegated to the if/then/else, then ERR_= EXIT could also be triggered at line 02 or 04, or worse at line 01 or 06, w= hich wouldn't let you know whether the non-zero status originated=C2=A0= from "cmd2" or from "cmd3". The delayed/delegated trigg= ering looks undesirable because it gives you less information on the origin= of the error. My understanding is that it's also never needed.

The behavior of ERR_EXIT is controlled by the variables &= quot;noerrexit" and "local_noerrexit". My understanding of t= hese variables is the following:

- noerrexit: This= variable is set to indicate that the triggering of ERR_EXIT must be disabl= ed in the evaluation of any word code from the point where it's set unt= il it's reset. For example it's set here in execif before the evaluation of the condition and reset here, here, here, and here after the evaluation of the condition. I don't really un= derstand why the reseting is so complicated. It's much more straightfor= ward=C2=A0in execwhile=C2=A0(here).

- local_noerrexit: This variable is set to indicate t= hat the triggering of ERR_EXIT must be disabled in the remainder of the eva= luation of the current word code. For example it's set at the end of ea= ch compound command, like here. This us= ed to be a plain "this_noerrexit =3D 1", which I don't think = was wrong.

I think my patches so far have uncovered a different bug that was
= already present but was masked by the foregoing, which is, that
noerrexi= t is unwound in cases where it should not be.=C2=A0 I think this is
happ= ening at lines 1530-1531 of exec.c, right under the comment about
"= hairy code near the end of execif()".=C2=A0 That's an area I didn&= #39;t touch,
but I'm pretty sure it's restoring noerrexit to its= state before
entering the "if" (oldnoerrexit) when it should = be preserving the
state from the "&&" conditional.=C2= =A0 In 5.8.1 this gets reversed again
via this_noerrexit.

I must admit that I don't understand the=C2=A0NOERREX= IT_UNTIL_EXEC logic here, nor the comp= licated resetting=C2=A0logic of noerrexit=C2=A0at the end of execif. I was = about to say that this doesn't seem to be the source of the problem bec= ause if, while, and for statements all behave the same in Zsh.
function fooIf1() =C2=A0 =C2=A0{ init; cond=3Dtrue; if =C2=A0 =C2= =A0$cond; then cond=3Dfalse; false =C2=A0 =C2=A0 =C2=A0 =C2=A0; fi =C2=A0; = }
function fooIf2() =C2=A0 =C2=A0{ init; cond=3Dtrue; if =C2=A0 =C2=A0$c= ond; then cond=3Dfalse; false && true; fi =C2=A0; }=C2=A0
=C2=A0
function fooWhile1() { init; cond=3Dtru= e; while $cond; do =C2=A0 cond=3Dfalse; false =C2=A0 =C2=A0 =C2=A0 =C2=A0; = done; }
function fooWhile2() { init; cond=3Dtrue; while $cond; do =C2=A0= cond=3Dfalse; false && true; done; }=C2=A0
=C2= =A0
function fooFor1() =C2=A0 { init; cond=3Dtrue; for v= in x ; do =C2=A0 cond=3Dfalse; false =C2=A0 =C2=A0 =C2=A0 =C2=A0; done; }<= br>function fooFor2() =C2=A0 { init; cond=3Dtrue; for v in x ; do =C2=A0 co= nd=3Dfalse; false && true; done; }

In the examples above fooIf1, fooWhile1, and fooFor1 all work correc= tly but fooIf2, fooWhile2, and fooFor2 fail to trigger ERR_EXIT in Zsh 5.8 = and trigger it too early (in foo instead of in bar) in Zsh 5.9.
<= br>
However, if I comment out the=C2=A0NOERREXIT_UNTIL_EXEC logic= in exec.c (or remove the negation), then fooIf2 and surprisingly=C2=A0also= fooFor2 work correctly in Zsh 5.9 but not fooWhile2!?! fooWhile2 still tri= ggers too early.

So it looks like this may indeed = be the start of the answer. But I'm still scratching my head on why tha= t is.

Philippe

--000000000000a6af7805ed5a791e--