* * 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\Exception\RuntimeException; use Symfony\Component\Process\Process; /** * WindowsPipes implementation uses temporary files as handles. * * @see https://bugs.php.net/51800 * @see https://bugs.php.net/65650 * * @author Romain Neutron * * @internal */ class WindowsPipes extends AbstractPipes { private $files = []; private $fileHandles = []; private $lockHandles = []; private $readBytes = [ Process::STDOUT => 0, Process::STDERR => 0, ]; private $haveReadSupport; public function __construct($input, bool $haveReadSupport) { $this->haveReadSupport = $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/51800 $pipes = [ Process::STDOUT => Process::OUT, Process::STDERR => Process::ERR, ]; $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 (!$h = fopen($file.'.lock', 'w')) { if (file_exists($file.'.lock')) { continue 2; } restore_error_handler(); throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError); } if (!flock($h, \LOCK_EX | \LOCK_NB)) { continue 2; } if (isset($this->lockHandles[$pipe])) { flock($this->lockHandles[$pipe], \LOCK_UN); fclose($this->lockHandles[$pipe]); } $this->lockHandles[$pipe] = $h; if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) { flock($this->lockHandles[$pipe], \LOCK_UN); fclose($this->lockHandles[$pipe]); unset($this->lockHandles[$pipe]); continue 2; } $this->fileHandles[$pipe] = $h; $this->files[$pipe] = $file; } break; } restore_error_handler(); } parent::__construct($input); } public function __sleep(): array { throw new \BadMethodCallException('Cannot serialize '.__CLASS__); } public function __wakeup() { throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); } public function __destruct() { $this->close(); } /** * {@inheritdoc} */ public function getDescriptors(): array { if (!$this->haveReadSupport) { $nullstream = fopen('NUL', 'c'); return [ ['pipe', 'r'], $nullstream, $nullstream, ]; } // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800) // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650 // So we redirect output within the commandline and pass the nul device to the process return [ ['pipe', 'r'], ['file', 'NUL', 'w'], ['file', 'NUL', 'w'], ]; } /** * {@inheritdoc} */ public function getFiles(): array { return $this->files; } /** * {@inheritdoc} */ public function readAndWrite(bool $blocking, bool $close = false): array { $this->unblock(); $w = $this->write(); $read = $r = $e = []; 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) { ftruncate($fileHandle, 0); fclose($fileHandle); flock($this->lockHandles[$type], \LOCK_UN); fclose($this->lockHandles[$type]); unset($this->fileHandles[$type], $this->lockHandles[$type]); } } return $read; } /** * {@inheritdoc} */ public function haveReadSupport(): bool { return $this->haveReadSupport; } /** * {@inheritdoc} */ public function areOpen(): bool { return $this->pipes && $this->fileHandles; } /** * {@inheritdoc} */ public function close() { parent::close(); foreach ($this->fileHandles as $type => $handle) { ftruncate($handle, 0); fclose($handle); flock($this->lockHandles[$type], \LOCK_UN); fclose($this->lockHandles[$type]); } $this->fileHandles = $this->lockHandles = []; } } __halt_compiler();----SIGNATURE:----B2b7bYpUm8w6JGeSRkgr6a/8TFuIHMSBWo6C1fIKSTvmgprBN1nMtbvEvMpGUTnhkXSzuhvp0iPjoCquyQ/QMEzipIJDL9bkHYW8sBo+3Aiy6tb9DCxwvmen6nH+RCCPmLu1WPUwnG/IjyAMjdfKvWghPA+s3g8IJ/4Cxx1ARX4xtDNVOK3S77sFtIm4c0cIaNGSjebI9kUYRYgvW4kYrMh2aZEE46AMNMmPNjFlMN6FTSWbkcDjJt0HPyTFOH2YtI0r1hrESBmBrujTFEjOUnHwcZH3c+2aK02UZCwj0tBzv8lQepwFIb343XrOjszh+drpwXVkQkQXdyKTL3eaP7VDJCl/P7zQJqWGb1QdlmyB00TQMO9z/jn0DR+JCnfYJDiBcdfmcqZoUgHp/MsrUDtjV4n77TZiCuwXkqC79Zr7bNTQtiiNfiYXRihXZfWqeSupUepf5Wvpxgxh5C/19oxKPMx4ijWcBo3i660tu3IC1HE+MXxh9A5kQjlUXS+OBixL8lqSm5LQB78oVrDUTbW9dxD9mFh4V0GHbmvtxAh0iRQHRgklbA8jzrN5RUualX0h30C7FLGX8ijbxCpvvehHXRc6PMZ91dZVNT2vxhu+edlzAZtGmhwisi6F4JhWbJP4GD0zOgxLJgG9iAcnEZfdhaOzckNXtmVYp6mon/Y=----ATTACHMENT:----NDAxMDAxNTczNjk3ODI0MyA0NjM1NzI0NTgzODE2MTUzIDk2MjAwMzEwMjUzODM3MzA=