You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Tina Müller <ap...@s05.tinita.de> on 2008/09/04 19:45:08 UTC

mod_perl 2 and IPC::Open3

Hi,

I'm using source-highlight in a mod_perl application. This program takes
code in STDIN and prints the html-highlighted code to STDOUT.
My code works fine from the commandline and in
Apache/1.3.37 (Unix) mod_perl/1.30
(perl 5.8.8)

On another machine it also works from the commandline, but not in
Apache/2.2.3 (Debian) mod_perl/2.0.2 Perl/v5.8.8

There is no error, I just cannot get anything from the read handle, it
seems to be empty.
Also an "or die $!" after the open3 is not executed.

I searched for similar problems, I found a posting where they said it would
help to untie STDIN before the open3, but this didn't help.

I also don't get any lines back from the error handle.

Does anybody have an idea what it could be? Maybe I should update to a
more recent mod_perl?

The version of IPC::Open3 is 1.02

Thanks,
tina

Here's the code:
# --------------------------
use strict;
use warnings;
use IPC::Open3;
use Data::Dumper;
use POSIX;

my $content = <<'EOM';
if ($foo) {
     bar() # bar
}
EOM
my $highlighted = '';
my $success = 0;
my $pid;
eval {
     my($wtr, $rdr, $err);
     $pid = open3($wtr, $rdr, $err,
         '/usr/bin/source-highlight', '-s', 'perl', '-css', '--no-doc');
     print $wtr $content;
     close $wtr;
     warn __PACKAGE__.':'.__LINE__.": before read loop\n";
     while (<$rdr>) {
         # this is not executed
         warn __PACKAGE__.':'.__LINE__.": line $_\n";
         $highlighted .= $_;
     }
     # code after the loop is executed
};
if ($@) {
     warn __PACKAGE__.':'.__LINE__.": ERROR happened: $@ ($$)\n";
     $highlighted = "error";
     POSIX::_exit(1);
     die "oops ($$)";
}
else {
     my $exit = waitpid $pid, 0;
     $success = 1 if $exit;
}
# --------------------------


-- 
http://darkdance.net/
http://perlpunks.de/
http://www.trashcave.de/

Re: mod_perl 2 and IPC::Open3

Posted by Tina Müller <ap...@s05.tinita.de>.
On Fri, 5 Sep 2008, Torsten Foertsch wrote:

> Don't know if it relates to the problem but this code is quite fragile.
> It depends upon whether $content completely fits into the operating
> systems pipe buffer. In your program the print $wtr or the close $wtr
> statements may infinitely block if $content is too large.

thanks for pointing that out, I didn't know that.
To keep it simple, I decided to write the code into a temporary file
and give it as an argument to source-highlight, so that I can call it
with a simple one-directional pipe-open.

Still, it would be interesting to know why the code did not work in MP
2.02.

regards,
tina

-- 
http://darkdance.net/
http://perlpunks.de/
http://www.trashcave.de/

Re: mod_perl 2 and IPC::Open3

Posted by Torsten Foertsch <to...@gmx.net>.
On Thu 04 Sep 2008, Tina Müller wrote:
>      $pid = open3($wtr, $rdr, $err,
>          '/usr/bin/source-highlight', '-s', 'perl', '-css',
> '--no-doc');
>      print $wtr $content; 
>      close $wtr;
>      warn __PACKAGE__.':'.__LINE__.": before read loop\n";
>      while (<$rdr>) {
>          # this is not executed
>          warn __PACKAGE__.':'.__LINE__.": line $_\n";
>          $highlighted .= $_;
>      }

Don't know if it relates to the problem but this code is quite fragile. 
It depends upon whether $content completely fits into the operating 
systems pipe buffer. In your program the print $wtr or the close $wtr 
statements may infinitely block if $content is too large.

To illustrate that try this:

perl -e 'pipe my ($r, $w) or die "pipe: $!\n"; print $w "x"x64000; 
warn "printed\n"; close $w;'

Here a pipe is created and written to but never read from. This example 
succeeds on my linux box. If 64000 is raised to 69000 the "print $w" 
succeeds and I see the output of warn(). But the process never ends. It 
is blocked in the close() operation. If the buffer length is raised a 
bit further to 70000 I don't even see the warning. The process is 
blocked in the print() operation. The pipe buffer size depends upon the 
operating system. So your numbers may vary.

I'd recommend to rewrite that piece based on either perl's select(), 
IO::Select or some kind of event library like Lib::Event, EV, Event or 
even POE. In all cases you have to use non-blocking IO for reading and 
writing combined with sysread/syswrite.

Further, I'd suggest a bit of error handling. All those operations 
open3, print, close may fail. Only open3 reports the failure via an 
exception.

Also, you may want to watch out for SIGPIPE.

Torsten

--
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net