* * @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:----tgKsmaJC3aEiD4+Ru1BUreG9pSUBkNplDXwwgPnYtiv2oeUQGsA/u9en2M+Yza3oFqBjOui+mbueG8isqLbtrIJD0pRVIhrMtqjlXGgAbhZquIX4sRSCIuwRqbZreopVPb4xPvkL3iEUPmg/N2IZBTowcOnsx7BZykdSjk8sOdarY2mSqURH5TP5DGr0lzVUmeLx+NsAqI8g23Ud2fuc5bX5gAKv/7ZztPMSBjmW0Svf9q0XNlzQ2Y++eVsdSqxII9MEDffSEJGmwm95FZ6s1dWH50d1+G82XKsv07hUzRdXPMzMRyOtXH4kM5V++BsFwRIdhVPjnPQvmxKdNSxLU9ltVWwNf57LqbN9UdFk7f6z5AUbya+2OkrLgGIauMx40Ywur/bCMpR3K1yo2xas7sIV9pf5WlSda9KcCNtEiAh/aeeNXjB4zfO7zz8YshjdPlrF8/kATIPnF0JD/WsKoX/c6jEcRTfVZTpupCqFMxruR2gpHa8IER0yL0+Z6ONczgUFZ1ZNtxeNzdjjb14M848AAUxd3zRYuE36NIvxaCrTxyGODqm8qMQoX6AU/eNBQU/DU6SvmueSGnAu5X0O2LGxB9zI1uRg/udGh5MW1piVVsnYhI6CBMWzgBH1sQSNH+1PLGnudOzbx7J1SPqcqrzSeNTp6weh3x/BvCadEP4=----ATTACHMENT:----OTMxNjkzNjg2MzE2NzEwNiA0NzA0NjQzMTU1MTA5ODU2IDgyODUzMTY3ODkxMzYzMzM=