zsh 5.6で行われたパイプのパラメタ展開のバグ修正


どんなバグか

zshでパイプを使ったとき最後の右端のコマンド以外は別プロセスのサブシェルで実行されます。したがって以下のようなことをしてもaへの値の設定はサブシェル側で実行され親へは影響しません。

% a=1 | cat; echo $a

しかし5.6になる前のzshでは以下のようなことをすると親の側のaに値を設定できてしまいました。

% echo ${a:=1} | cat ; echo $a
1
1

また$jobstatusなどの特別なパラメタがサブシェルの状態ではなく親側の状態に基づく値に展開されてしまっていました。

これはなぜかパラメタ展開をforkする前の親プロセスの側で行うようになっていたからです。結構長いことこの状態だったようなのですが、パラメタ展開をサブシェル側で行うようにすることで、5.6以降はこの問題は修正されました。

影響

このせいでzplugのインストーラーがインストール完了前に終了してしまうようになりました。(報告済み) もともとこちらがきっかけで調べ始めてたどり着いたわけですが。

でもこの件は単なるバグフィックスという位置づけらしく、READMEのIncompatibilities since ...やNEWSでは全く触れられていなくて、かろうじてChangeLogに以下のような記述があるのみです。

2018-05-01  Peter Stephenson  <[email protected]>

    * from branch fork_early, c.f. 42702: Src/exec.c: Various changes
    to make forking for a command work better.  Move the fork even
    earlier; add case of non-final pipeline elements; _exit when
    forked; remove previous early fork in caller; replace fix for
    leaked file descriptor in pipeline handling.

これでわかれといわれてもかなりつらい。