IPC::Open3::open3に関するメモ

Plack::Middleware::File::Less を lessc でコンパイルするように - naoyaのはてなダイアリー


で紹介されている。Plack::Middleware::File::Lessのソースの
以下の部分が気になりました。

sub less_command {
    my $less = shift;
    my $pid = open3(my $in, my $out, my $err, "lessc", "-");
    print $in $less;
    close $in;

    my $buf = join '', <$out>;
    waitpid $pid, 0;

    return $buf;
}

標準エラー出力に書きまくるような LESSを入力に与えれば、
blockした状態になりつづけるんじゃないかなって思って試して
みたんですけど、どうもうまくいきません。参考記事から 0(false)を
指定すると、標準エラー出力が標準出力に dupされることは知っていたの
ですが、これは undefだしハンドルが設定されるんじゃないかなって思って
IPC::Open3のソースを確認してみたのですが、undefでも dupされてしまった
ようです。


問題の部分は以下でした。

# IPC::Open3::_open3関数 209行目
 $handles[2]{parent} ||= $handles[1]{parent};

ハッシュの要素なので undefでも特に問題なく dupされていたようです。
以下のように書かれていたらわかったと思うんですが・・・。

    my $pid = open3(my $in, my $out, 0, "lessc", "-");

まだまだ Perl力が低かったです。

おわりに

たぶんこのことを見越して書かれたコードなのだとは思いますが、
自分で書くときは 0にしておかないと読み間違えてしまいそうだなと
思いました。なお明示的に標準エラー出力のハンドラを設定したい
場合は, Symbol::gensym関数を変数に設定して、第三引数として
設定してください。詳しくはドキュメントを見てください。