Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warning: proc_open(): CreateProcess failed, error code - 2 #56

Closed
Bilna75 opened this issue Jul 8, 2014 · 14 comments
Closed

Warning: proc_open(): CreateProcess failed, error code - 2 #56

Bilna75 opened this issue Jul 8, 2014 · 14 comments

Comments

@Bilna75
Copy link

Bilna75 commented Jul 8, 2014

Hi,
I'm currently trying to use your wkhtmltopdf but I cannot get passed a Warning call saying :

Warning: proc_open() [function.proc-open]: CreateProcess failed, error code - 87 in Path/To/WkHtmlToPdf.php on line 325

I tried with a basic code given in the tutorial but it doesn't work.

$pdf = new WkHtmlToPdf;
$pdf->addPage('http://google.com');
$pdf->send();

The error code 87 stands for invalid parameter.
Anyone can help me ?

Thank you

@mikehaertl
Copy link
Owner

Sorry, I don't use Windows, so I can't really help. Other Windows users seem to have no problem with the library. You will have to play around with proc_open() yourself to find out, what's wrong. I'd try to build a simple PHP script and use more and more complex shell commands with proc_open().

Hope this helps.

@tivie
Copy link
Contributor

tivie commented Oct 24, 2014

There are a lot of issues with php proc_open on windows. See:

https://bugs.php.net/bug.php?id=51800

https://bugs.php.net/bug.php?id=60120

https://bugs.php.net/bug.php?id=65650

One workaround is to run the command yourself using exec().

However, as far as I know, there's no way to get the command woithout actually running it. I've created a pull request that should address this issue.

@mikehaertl
Copy link
Owner

If we wanted to fix this, we should do so in the underlying https://github.com/mikehaertl/php-shellcommand. But I'm hesitant to do so. proc_open() gives you full access to return value, STDIN and STDOUT. You can't do that with exec().

The problem seems only to happen with long output (longer than 4096 bytes) on windows.. So I wonder, if adding the quiet option doesn't fix the problem.

@tivie
Copy link
Contributor

tivie commented Oct 25, 2014

The problem seems only to happen with long output (longer than 4096 bytes) on windows.. So I
wonder, if adding the quiet option doesn't fix the problem.

Unfortunately, this is not quite so simple. I've tested on two machines, a i7 3.4Ghz desktop and a dual Xeon E5-2695 server, both running the same exact OS and IIS 7.5)

On the desktop, the php script times-out when converting a 233Kb html file + 295K worth of images to a 757kb pdf. Increasing the time-out time (to hours) on php doesn't fix the problem. The strange thing is that while the script is running, the PDF in the temp directory is empty but immidiately after timing out, the PDF gets created correctly in the temp directory. I can't explain this behaviour.

Things get even weirder in the server. Sometimes the above script works without any problem, other times it behaves like the desktop. It's totally unreliable.

If we wanted to fix this, we should do so in the underlying https://github.com/mikehaertl/php-
shellcommand. But I'm hesitant to do so. proc_open() gives you full access to return value, STDIN
and STDOUT.

I agree. proc_open gives you more control over the process and works great on *nix environment. However, unless you're planning to add further features in error digest, as your script stands right now, there's no real difference in using exec or proc_open. Since you're not really digesting stdErr anyways, just using the exit code, passing a third argument to exec gets you the same result

What I propose is either:

  • give the option to select which function to use in the script: exec or proc_open (through setOption). Maybe have a sensible default (in windows OS it defaults to exec all the others get proc_open). This gives you more flexibility to future features additions in terms of error handling and logging, but increases code complexity and is harder to maintain and test.
  • or drop proc_open altogether in favor of exec. Simpler code, easier to maintain, but you might lose the possibility to add complex error handling in the future.

@mikehaertl
Copy link
Owner

Since you're not really digesting stdErr anyways, just using the exit code, passing a third argument to exec gets you the same result

It is used. See https://github.com/mikehaertl/phpwkhtmltopdf/blob/master/src/Pdf.php#L248.

Things get even weirder in the server. Sometimes the above script works without any problem, other times it behaves like the desktop. It's totally unreliable.

So... there's an issue anyway, even on the shell? How can we know, that this is really related to proc_open() then? This sounds like a different problem to me.

I still recommend to try the quiet option with wkhtmltopdf. This should at least workaround the above proc_open() issues.

@tivie
Copy link
Contributor

tivie commented Oct 27, 2014

So... there's an issue anyway, even on the shell? How can we know, that this is really related to
proc_open() then? This sounds like a different problem to me.

No, I might have not explained the issue clearly.

TEST 1

I created the following script (gist) and tested it in both my Desktop and my Home Server.

Results:

  • In the Desktop the scripts always fails.
  • In the Server the script fails most of the times (in 100 tries it failed 83). The pattern seems random and unrelated to memory or CPU load.
  • Removing the header and footer lines in options array makes the script run 100% of the times.
  • However, running the produced command (see below) in the "command line" works 100% of the times in both machines. Takes 9013 ms to run in the Desktop.
  • The produced PDF has a size of 332Kb.

(produced phpWkHtmlToPdf command)
wkhtmltopdf --no-outline --enable-local-file-access --encoding "UTF-8" --disable-smart-shrinking --margin-left "0" --margin-right "0" --margin-top "45mm" --margin-bottom "25mm" --header-html "F:\tmp\wktest\inc\header.html" --footer-html "F:\tmp\wktest\inc\footer.html" "htmlfile.html" "F:\tmp\tmpEAAD.tmp.pdf"

TEST 2

I changed mikehaertl\shellcommand\Command execute() method as seen in this gist, to use exec instead of proc_open().

Results

  • Works 100% of the times in both Desktop and Server
  • Takes about 9074ms to run in the Desktop.
  • Produces the same PDF.

@tivie
Copy link
Contributor

tivie commented Oct 27, 2014

Since you're not really digesting stdErr anyways, just using the exit code, passing a third argument to exec gets you the same result

It is used. See https://github.com/mikehaertl/phpwkhtmltopdf/blob/master/src/Pdf.php#L248.

Yes, I know it's used but it's not being parsed. wkHtmlToPdf library writes progress to STDERR: see https://code.google.com/p/wkhtmltopdf/issues/detail?id=825. This is by deisgn since they support dumping the actual PDF to STDOUT.

So what I meant was: since your library does not really use STDOUT for anything, and since wkHtmlToPdf dumps the progress to STDERR, regardless of it having error messages, using proc_open or exec is the same thing.

Why?

Because you can pipe STDERR to STDOUT (and STDOUT to Nul) with exec and then read from it which, in pratical terms it's the same as reading from STDERR with proc_open.

GIST

public function execute()
{
    $command = $this->getExecCommand();

    if (!$command) {
        return false;
    }

    $command = $command . ' 2>&1';

    $lastLine = exec($command, $otp, $this->_exitCode);
    $this->_stdErr = implode('', $otp);

    if ($this->_exitCode!==0) {
        $this->_error = $lastLine ? $lastLine : "Failed without error message: $command";
        return false;
    }
    $this->_executed = true;
    return true;
}

@mikehaertl
Copy link
Owner

@tivie I've now update the php-shellcommand. You should be able to do this now:

<?php
use mikehaertl\wkhtmlto\Pdf;
$pdf = new Pdf([
    'commandOptions' => [
        'useExec' => true,
    ],
]);
...

Can you please help testing?

@tivie
Copy link
Contributor

tivie commented Nov 5, 2014

@mikehaertl Thanks Michael. I will be testing it and post the results soon.

@tivie
Copy link
Contributor

tivie commented Nov 5, 2014

@mikehaertl The new commandOption is working good (passed all my tests). However, error reporting is lacking. I've fixed this issue in this pull request. Michael, if you don't mind, please have a look.

@tivie
Copy link
Contributor

tivie commented Jul 3, 2015

@mikehaertl I've created a command exec library that address inconsistencies between linux and windows environments. You might wanna consider using it to build your lib commands.

https://github.com/tivie/command

If you wish, I can help you implement this.

@mikehaertl
Copy link
Owner

@tivie That looks nice. Maybe something to consider for a 3.0 release. On the other hand, from looking at the code I couldn't actually find a big difference in the core part (proc_open()). If you have some hints how to improve my php-shellcommand, I'm happy to include those changes. Your class makes sense for more advanced scenarios (method chaining, etc.). But our use case here is pretty simple. And I still believe in my own php-shellcommand implemenation ;).

BTW you may also hit this problem: mikehaertl/php-shellcommand#6. Maybe worth adding to your class, too?

@tivie
Copy link
Contributor

tivie commented Jul 4, 2015

@mikehaertl thanks.

The only big difference is in the automatic selection of proc_open or exec based on OS (in windows it uses exec, otherwise uses proc_open.)

If you have some hints how to improve my php-shellcommand, I'm happy to include those changes

Maybe add this:

  • Automatic fallback to exec in windows environments
  • A way to change the produced command before executing it

Those two would be awesome.

BTW you may also hit this problem: mikehaertl/php-shellcommand#6. Maybe worth adding to your class, too?
Yeah, that's worth adding as an opt-in option when dealing with long outputs. Thanks for the suggestion. =)

@doshu
Copy link

doshu commented May 5, 2017

use the bypass_shell options of proc_open to make it works on windows

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants