Search code examples
perlipcmason

Why IPC::Run3 cannot capture any standard output in Apache environment?


%use IPC::Run3;
%my $a;
%run3 ['echo','hello'],\undef,\$a;
<% $a %>

Above mason code works very well when I use Mason from a standalone script, as descriped in HTML::Mason::Admin. Unfortunately, when running with perl_mode, $a is an empty string. Below is my httpd.conf

 Alias /mason_book /home/charlse/f/books/mason_book
 <Location /mason_book>
    SetHandler perl-script
    AddHandler perl-script .mas
    PerlHandler HTML::Mason::ApacheHandler
    PerlAddVar  MasonCompRoot  "mason_book => /home/charles/f/books/mason_book"
 </Location>
 <Directory "/home/chunywan/f/books/mason_book">
    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
 </Directory>

BTW

 %use IPC::Run qw(run timeout);
 %my @cmd=qw(echo hello world);
 %my ($in,$out,$err);
 %run(\@cmd, \$in, \$out, \$err) or die "cat: $?";
 <pre>
   out <% $out %>
 </pre>

I just try IPC::Run which works very well in both standalone mode and mod_perl mode. It seems that I have to update all my source code to use IPC::Run instead of IPC::Run3.


Solution

  • I believe the solution is to temporarily re-open STDIN/STDOUT, and then close it after your command finishes.

    use IPC::Run3;
    my $a;
    
    #save off existing stdin/out
    my ($save_stdin,$save_stdout);
    open $save_stdin, '>&STDIN';
    open $save_stdout, '>&STDOUT';
    
    #open it again as the "normal things"
    open STDIN, '>&=0';
    open STDOUT, '>&=1';
    run3 ['echo','hello'],\undef,\$a;
    
    #clean up after yourself
    close(STDIN);
    close(STDOUT);
    open STDIN, '>&', $save_stdin;
    open STDOUT, '>&', $save_stdout;
    

    I ran into the same issue with IPC::Open3 and solved it here: https://stackoverflow.com/a/24311232/312208