symfony/symfony — pull request #10420 by romainneutron (2014-03-11 16:49:07+00:00)
Title: [2.3][Process] Make Process::start non-blocking on Windows platform

| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #9755
| License | MIT

This PR is a proposition that solves issue #9755.

Let me sum-up what problems we have on Windows platform:
- We can not use pipes with `proc_open` on Windows because `stream_set_blocking` does not work on this platform, resulting in blocking pipes and a blocking `Process::start` (see https://bugs.php.net/bug.php?id=51800, https://bugs.php.net/bug.php?id=47918 and https://bugs.php.net/bug.php?id=50856).
- We can not use file handles for both `STDOUT` and `STDERR` as it might produce corrupted content (see https://bugs.php.net/bug.php?id=65650).
- We currently use file handles for `STDOUT` and pipe for `STDERR` but it makes `Process::start` blocking.

The solution I propose here is to use native redirections, write `STDERR` / `STDOUT` in temporary files, read these files, finally cleanup.
It works pretty well, all tests pass on Windows. Better : [previous tests that were specific to this platform](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Process/Tests/AbstractProcessTest.php#L720-725) disappear as unix one are now okay :).

The drawback of this is the need of using `taskkill`: When stopping a process (`Process::stop` or in case of a timeout reached) `proc_terminate` does not kill the underlying process properly, only the `cmd` parent. The underlying process run by Process still runs after the `proc_terminate` call, having a lock on the temporary files we're using for getting the output, avoiding PHP to remove them (or any user on system) until the underlying process has finish to run).
So I use the `taskkill` Windows command to terminate the underlying process. This works well but I've to admit it's not pretty. If we do not use this hack, let's face that the underlying process is not stopped.

Last but not least, let's deal with the case we're running on Windows platform with PHP having --enable-sigchild environment (I don't know if it can really happen)
In this case:
- we can not retrieve the `pid`
- we can not `taskkill` the underlying process
- it runs
- locks remain on temporary files, we might not be able to remove them
We can't really deal with this.

Feedback more than welcome