1

I had a PHP script that relied on shell_exec() and (as a result) worked 99% of the time. The script executed a PhantomJS script that produced an image file. Then using more PHP that image file was processed in a certain way. Problem was that on occasion shell_exec() would hang and cause usability issues. Reading this https://github.com/ariya/phantomjs/issues/11463 I learnt that shell_exec() is the problem and switching to proc_open would solve the hanging.

The problem is that while shell_exec() waits for the executed command to finish proc_open doesn't, and so the PHP commands that follow it and work on the generated image fail as the image is still being produced. I'm working on Windows so pcntl_waitpid is not an option.

My initial approach was to try and get PhantomJS to continuously output something for proc_open to read. You can see what I tried in this thread:

Get PHP proc_open() to read a PhantomJS stream for as long as png is created

I couldn't get this to work and seems no one else has a solution for me. So what I'm asking now is how can I make proc_open work synchronously like shell_exec. I need for the remaining PHP commands in my scripts to be executed only after the proc_open command ends.

Adding my code as per first comment request:

ob_implicit_flush(true);
$descriptorspec = array(
    0 => array("pipe", "r"),  // stdin
    1 => array("pipe", "w"),  // stdout
    2 => array("pipe", "w")   // stderr 
);

$process = proc_open ("c:\phantomjs\phantomjs.exe /test.js", $descriptorspec, $pipes);
if (is_resource($process))
{
while( ! feof($pipes[1]))
  {
     $return_message = fgets($pipes[1], 1024);
     if (strlen($return_message) == 0) break;
     echo $return_message.'<br />';
     ob_flush();
     flush();
  }
}

Here is the PhantomJS script:

interval = setInterval(function() {
  console.log("x");
}, 250);
var page = require('webpage').create();
var args = require('system').args;
page.open('http://www.cnn.com', function () {
  page.render('test.png');
  phantom.exit();
});

If instead of "c:\phantomjs\phantomjs.exe /test.js" I use a cmd.exe ping form exmaple I get line after line of $return_message printed, so I know proc_open receives a stream. I'm trying to get the same to happen with the Phantom script.

Community
  • 1
  • 1
Liam Arbel
  • 467
  • 1
  • 7
  • 14
  • how about adding some code to show us what you do there? – Twisted1919 Aug 01 '14 at 11:00
  • From your code i don't think php is the issue, rather you js code where it doesn't block and most probably the script finish execution before the callback is being processed. Maybe block after page.open call and release when that call finishes. – Twisted1919 Aug 01 '14 at 11:25
  • twisted can you be more specific about the block in the js code. I'm not a big js expert and could sure use a little more guidance! thank you – Liam Arbel Aug 01 '14 at 11:45
  • this is from my very small experience with nodejs, don't know it it applies here. Your `page.open` call will basically send the callback in background until it finishes but the script processing will not stop at that call (since it has been sent in background) and will continue without throwing any info to you. Maybe do something along the lines: `var isDone = 0; page.open('http://www.cnn.com', function (){page.render('test.png'); isDone = 1; }); setInterval(function(){ if(isDone) {phantom.exit();} }, 200)` – Twisted1919 Aug 01 '14 at 11:53

0 Answers0