0

From within embperl, I am trying to call wkhtmltopdf with the IPC::Open3 module.

I get output (thanks to ikegami ) from wkhtmltopdf but no input is going to wkhtmltopdf.

This is related to this question: perl / embperl — IPC::Open3

Here is the code:

[-
  use warnings;
  use strict;
  use IPC::Open3;
  use POSIX;
  use Symbol;

  my $cmd = '/usr/local/bin/wkhtmltopdf - -';

  my $pdf = '';

  my $string = '<!DOCTYPE html>
  <html>
    <head>
      <title>Hello World</title>
     </head>
     <body>
       Hello World!!!
     </body>
     </html>';

  my $fhOUT = gensym();
  open($fhOUT, '>', '/dev/null') or die $!; 
  dup2(fileno($fhOUT), 1) or die $! if fileno($fhOUT) != 1;
  local *STDOUT;
  open(STDOUT, '>&=', 1) or die $!;

  my $pid = open3(*HIS_IN, *HIS_OUT, *HIS_ERR, $cmd)  or die "could not run cmd : $cmd : $!\n";

  print HIS_IN $string;
  close(HIS_IN);

  while( <HIS_OUT> ) {
    $pdf .= $_;
  }


  waitpid($pid, 0 ) or die "$!\n";
  my $retval =  $?;
  # print "retval-> $retval<br />\n";

  $http_headers_out{'Content-Type'}         = "application/pdf";
  $http_headers_out{'Content-Disposition'}  = "attachment; filename=pdfTest.pdf";

  $escmode = 0;
-]
[+ $pdf +]
Community
  • 1
  • 1
Donavon Lerman
  • 343
  • 1
  • 6
  • 19

1 Answers1

0

Same idea for STDIN, but fd 0 instead of 1.

 open(my $fhIN, '<', '/dev/null') or die $!;
 dup2(fileno($fhIN), 0) or die $! if fileno($fhIN) != 0;
 local *STDIN; open(STDIN, '<&=', 0) or die $!;

 open(my $fhOUT, '>', '/dev/null') or die $!;
 dup2(fileno($fhOUT), 1) or die $! if fileno($fhOUT) != 1;
 local *STDOUT; open(STDOUT, '>&=', 1) or die $!;

 my $pid = open3(
    local *HIS_IN,
    local *HIS_OUT,
    '>&STDERR',
    $cmd
 );

 ...

This assumes fd 0 and 1 are closed, as is the case here.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Hello ikegami. Thank you for taking the time to answer. It seems to work but now there is a **defunct process** showing up in the process list. `apache 24480 24396 0 14:34 ? 00:00:00 [wkhtmltopdf] ` – Donavon Lerman May 27 '14 at 21:39
  • A defunct process is one that hasn't bee reaped (e.g. using `wait` or `waitpid`). – ikegami May 27 '14 at 21:54
  • I added the waitpid and it works when I add `open(my $fhIN, '<', '/dev/null') or die $!; dup2(fileno($fhIN), 0) or die $! if fileno($fhIN) != 0; local *STDIN; open(STDIN, '<&=', 0) or die $!;` After that, I can't output anything to through html. It writes to a file fine so I know it works but I can not write to the browser. – Donavon Lerman May 27 '14 at 22:28
  • You have a system were the file handkes and file descriptors are severely messed up. Looks like we clobbered the file descriptor you're using for output, so you'll need to back it up. – ikegami May 27 '14 at 22:58
  • How do I un-clobber the file descriptor/handle after it's done with the open3() part? – Donavon Lerman May 27 '14 at 23:22
  • dup2 to a temp number, then dup2 back to the original number. Perhaps. This is getting very very complicated. Normally, you'd do this stuff post-fork. – ikegami May 28 '14 at 00:56