Mercurial > hg > isophonics-drupal-site
diff vendor/symfony/process/Pipes/WindowsPipes.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vendor/symfony/process/Pipes/WindowsPipes.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,200 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Process\Pipes; + +use Symfony\Component\Process\Process; +use Symfony\Component\Process\Exception\RuntimeException; + +/** + * WindowsPipes implementation uses temporary files as handles. + * + * @see https://bugs.php.net/bug.php?id=51800 + * @see https://bugs.php.net/bug.php?id=65650 + * + * @author Romain Neutron <imprec@gmail.com> + * + * @internal + */ +class WindowsPipes extends AbstractPipes +{ + /** @var array */ + private $files = array(); + /** @var array */ + private $fileHandles = array(); + /** @var array */ + private $readBytes = array( + Process::STDOUT => 0, + Process::STDERR => 0, + ); + /** @var bool */ + private $haveReadSupport; + + public function __construct($input, $haveReadSupport) + { + $this->haveReadSupport = (bool) $haveReadSupport; + + if ($this->haveReadSupport) { + // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. + // Workaround for this problem is to use temporary files instead of pipes on Windows platform. + // + // @see https://bugs.php.net/bug.php?id=51800 + $pipes = array( + Process::STDOUT => Process::OUT, + Process::STDERR => Process::ERR, + ); + $tmpCheck = false; + $tmpDir = sys_get_temp_dir(); + $lastError = 'unknown reason'; + set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); + for ($i = 0;; ++$i) { + foreach ($pipes as $pipe => $name) { + $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); + if (file_exists($file) && !unlink($file)) { + continue 2; + } + $h = fopen($file, 'xb'); + if (!$h) { + $error = $lastError; + if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) { + continue; + } + restore_error_handler(); + throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error)); + } + if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) { + continue 2; + } + if (isset($this->files[$pipe])) { + unlink($this->files[$pipe]); + } + $this->files[$pipe] = $file; + } + break; + } + restore_error_handler(); + } + + parent::__construct($input); + } + + public function __destruct() + { + $this->close(); + $this->removeFiles(); + } + + /** + * {@inheritdoc} + */ + public function getDescriptors() + { + if (!$this->haveReadSupport) { + $nullstream = fopen('NUL', 'c'); + + return array( + array('pipe', 'r'), + $nullstream, + $nullstream, + ); + } + + // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) + // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 + // So we redirect output within the commandline and pass the nul device to the process + return array( + array('pipe', 'r'), + array('file', 'NUL', 'w'), + array('file', 'NUL', 'w'), + ); + } + + /** + * {@inheritdoc} + */ + public function getFiles() + { + return $this->files; + } + + /** + * {@inheritdoc} + */ + public function readAndWrite($blocking, $close = false) + { + $this->unblock(); + $w = $this->write(); + $read = $r = $e = array(); + + if ($blocking) { + if ($w) { + @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); + } elseif ($this->fileHandles) { + usleep(Process::TIMEOUT_PRECISION * 1E6); + } + } + foreach ($this->fileHandles as $type => $fileHandle) { + $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]); + + if (isset($data[0])) { + $this->readBytes[$type] += strlen($data); + $read[$type] = $data; + } + if ($close) { + fclose($fileHandle); + unset($this->fileHandles[$type]); + } + } + + return $read; + } + + /** + * {@inheritdoc} + */ + public function haveReadSupport() + { + return $this->haveReadSupport; + } + + /** + * {@inheritdoc} + */ + public function areOpen() + { + return $this->pipes && $this->fileHandles; + } + + /** + * {@inheritdoc} + */ + public function close() + { + parent::close(); + foreach ($this->fileHandles as $handle) { + fclose($handle); + } + $this->fileHandles = array(); + } + + /** + * Removes temporary files. + */ + private function removeFiles() + { + foreach ($this->files as $filename) { + if (file_exists($filename)) { + @unlink($filename); + } + } + $this->files = array(); + } +}