ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
WindowsPipes.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11 
13 
16 
28 {
30  private $files = array();
32  private $fileHandles = array();
34  private $readBytes = array(
35  Process::STDOUT => 0,
36  Process::STDERR => 0,
37  );
40 
42  {
43  $this->haveReadSupport = (bool) $haveReadSupport;
44 
45  if ($this->haveReadSupport) {
46  // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
47  // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
48  //
49  // @see https://bugs.php.net/bug.php?id=51800
50  $pipes = array(
53  );
54  $tmpDir = sys_get_temp_dir();
55  $error = 'unknown reason';
56  set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
57  for ($i = 0;; ++$i) {
58  foreach ($pipes as $pipe => $name) {
59  $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
60  if (file_exists($file) && !unlink($file)) {
61  continue 2;
62  }
63  $h = fopen($file, 'xb');
64  if (!$h && false === strpos($error, 'File exists')) {
65  restore_error_handler();
66  throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
67  }
68  if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
69  continue 2;
70  }
71  if (isset($this->files[$pipe])) {
72  unlink($this->files[$pipe]);
73  }
74  $this->files[$pipe] = $file;
75  }
76  break;
77  }
78  restore_error_handler();
79  }
80 
81  parent::__construct($input);
82  }
83 
84  public function __destruct()
85  {
86  $this->close();
87  $this->removeFiles();
88  }
89 
93  public function getDescriptors()
94  {
95  if (!$this->haveReadSupport) {
96  $nullstream = fopen('NUL', 'c');
97 
98  return array(
99  array('pipe', 'r'),
100  $nullstream,
101  $nullstream,
102  );
103  }
104 
105  // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800)
106  // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650
107  // So we redirect output within the commandline and pass the nul device to the process
108  return array(
109  array('pipe', 'r'),
110  array('file', 'NUL', 'w'),
111  array('file', 'NUL', 'w'),
112  );
113  }
114 
118  public function getFiles()
119  {
120  return $this->files;
121  }
122 
126  public function readAndWrite($blocking, $close = false)
127  {
128  $this->unblock();
129  $w = $this->write();
130  $read = $r = $e = array();
131 
132  if ($blocking) {
133  if ($w) {
134  @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
135  } elseif ($this->fileHandles) {
136  usleep(Process::TIMEOUT_PRECISION * 1E6);
137  }
138  }
139  foreach ($this->fileHandles as $type => $fileHandle) {
140  $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
141 
142  if (isset($data[0])) {
143  $this->readBytes[$type] += strlen($data);
144  $read[$type] = $data;
145  }
146  if ($close) {
147  fclose($fileHandle);
148  unset($this->fileHandles[$type]);
149  }
150  }
151 
152  return $read;
153  }
154 
158  public function haveReadSupport()
159  {
160  return $this->haveReadSupport;
161  }
162 
166  public function areOpen()
167  {
168  return $this->pipes && $this->fileHandles;
169  }
170 
174  public function close()
175  {
176  parent::close();
177  foreach ($this->fileHandles as $handle) {
178  fclose($handle);
179  }
180  $this->fileHandles = array();
181  }
182 
186  private function removeFiles()
187  {
188  foreach ($this->files as $filename) {
189  if (file_exists($filename)) {
190  @unlink($filename);
191  }
192  }
193  $this->files = array();
194  }
195 }
$error
Definition: Error.php:17
getDescriptors()
{Returns an array of descriptors for the use of proc_open.array}
areOpen()
{Returns if the current state has open file handles or pipes.bool}
$h
getFiles()
{Returns an array of filenames indexed by their related stream in case these pipes use temporary file...
$w
$r
Definition: example_031.php:79
close()
{Closes file handles and pipes.}
Create styles array
The data for the language used.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
WindowsPipes implementation uses temporary files as handles.
haveReadSupport()
{Returns if pipes are able to read output.bool}
readAndWrite($blocking, $close=false)
{Reads data in file handles and pipes.Whether to use blocking calls or not Whether to close pipes if ...