IPC::Open2 (Open3) が Catalyst のテストサーバでまともに動かない。ハンドルを操作しようとすると Broken pipe のエラーが起きる。
package MyApp::Controller::Foo; sub foo :Private { my ( $self, $c ) = @_; open2( my $out, my $in, "/path/to/command" ); print $in "input" or die $!; # <-- Broken pipe
検索して Re: [Catalyst] Catalyst and IPC::Open2 を見つけた。それによると
STDOUT and STDERR probably aren't what it expects.
Try doing the same save+restore trick I use here -
http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-Controller-WrapCGI/lib/Catalyst/Controller/WrapCGI.pm
STDIN と STDOUT が期待してるのと違っちゃってるから C::C::WrapCGI みたいなトリックを使えと。
実際、Catalyst::Engine::HTTP では
sub _handler { my ( $self, $class, $port, $method, $uri, $protocol ) = @_; local *STDIN = \*Remote; local *STDOUT = \*Remote;
こんなことをしてるのだった。
てことで、Catalyst::Controller::WrapCGI からコードをもらってきて myapp_server.pl で以下のような対処をして解決。require MyApp; から MyApp->run の間にコードを追加。
require MyApp; open my $REAL_STDIN, "<&=".fileno(*STDIN); open my $REAL_STDOUT, ">>&=".fileno(*STDOUT); sub MyApp::dispatch { my $class = shift; local *STDIN = $REAL_STDIN; # restore the real ones so the filenos local *STDOUT = $REAL_STDOUT; # are 0 and 1 for the env setup my $old = select($REAL_STDOUT); # in case somebody just calls 'print' $class->NEXT::dispatch(@_); select $old; }; MyApp->run( $port, $host, {