Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

BUG: Always blocks perform tail call process optimization



When the last command of a subshell is another subshell or an external command, Zsh reuses the subshell's process instead of forking. Zsh allows this optimization in try blocks of always statements. This leads to bogus exit statuses.

Test script (note that all always statements are surrounded by a subshell):
if [[ -v ZSH_EXEPATH ]]; then alias zsh=$ZSH_EXEPATH; fi;
zsh --version;

zsh <<EOF
({
  echo "false"
} always {
  false
})
EOF
echo status=$?
echo

zsh <<EOF
({
  echo "/usr/bin/false"
} always {
  /usr/bin/false
})
EOF
echo status=$?
echo

zsh <<EOF
({
  echo "( false )"
} always {
  ( false )
})
EOF
echo status=$?
echo

zsh <<EOF
({
  echo "( return 42 )"
} always {
  ( return 42 )
})
EOF
echo status=$?
echo


Output:
zsh 5.9.0.2-test (x86_64-apple-darwin24.4.0)
false
status=0

/usr/bin/false
status=1

( false )
status=1

( return 42 )
status=42


All statuses in the output should be equal to 0. What happens, is that when Zsh executes /usr/bin/false, it reuses the process of the subshell surrounding the always statement. Thus, this subshell becomes /usr/bin/false and when it terminates there is no longer any subshell around to replace its exit status with the exit status of the try block. Instead the exit status of /usr/bin/false becomes the exit status of the surrounding subshell.

The attached patch fixes the issues (and doesn't break any existing test). If everyone agrees with this I can add a test. If you know in which file it should go, let me know.

Philippe

diff --git a/Src/loop.c b/Src/loop.c
index 979285abc..ba01b1da5 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -774,7 +774,7 @@ exectry(Estate state, int do_exec)
     contflag = 0;
 
     state->pc = always;
-    execlist(state, 1, do_exec);
+    execlist(state, 1, 0);
 
     if (try_errflag)
 	errflag |= ERRFLAG_ERROR;

Attachment: always-tail-call.zsh
Description: Binary data



Messages sorted by: Reverse Date, Date, Thread, Author