Mercurial > hg > cmmr2012-drupal-site
comparison vendor/symfony/process/Pipes/WindowsPipes.php @ 4:a9cd425dd02b
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:11:55 +0000 |
parents | c75dbcec494b |
children |
comparison
equal
deleted
inserted
replaced
3:307d7a7fd348 | 4:a9cd425dd02b |
---|---|
9 * file that was distributed with this source code. | 9 * file that was distributed with this source code. |
10 */ | 10 */ |
11 | 11 |
12 namespace Symfony\Component\Process\Pipes; | 12 namespace Symfony\Component\Process\Pipes; |
13 | 13 |
14 use Symfony\Component\Process\Exception\RuntimeException; | |
14 use Symfony\Component\Process\Process; | 15 use Symfony\Component\Process\Process; |
15 use Symfony\Component\Process\Exception\RuntimeException; | |
16 | 16 |
17 /** | 17 /** |
18 * WindowsPipes implementation uses temporary files as handles. | 18 * WindowsPipes implementation uses temporary files as handles. |
19 * | 19 * |
20 * @see https://bugs.php.net/bug.php?id=51800 | 20 * @see https://bugs.php.net/bug.php?id=51800 |
24 * | 24 * |
25 * @internal | 25 * @internal |
26 */ | 26 */ |
27 class WindowsPipes extends AbstractPipes | 27 class WindowsPipes extends AbstractPipes |
28 { | 28 { |
29 private $files = array(); | 29 private $files = []; |
30 private $fileHandles = array(); | 30 private $fileHandles = []; |
31 private $readBytes = array( | 31 private $lockHandles = []; |
32 private $readBytes = [ | |
32 Process::STDOUT => 0, | 33 Process::STDOUT => 0, |
33 Process::STDERR => 0, | 34 Process::STDERR => 0, |
34 ); | 35 ]; |
35 private $haveReadSupport; | 36 private $haveReadSupport; |
36 | 37 |
37 public function __construct($input, $haveReadSupport) | 38 public function __construct($input, $haveReadSupport) |
38 { | 39 { |
39 $this->haveReadSupport = (bool) $haveReadSupport; | 40 $this->haveReadSupport = (bool) $haveReadSupport; |
41 if ($this->haveReadSupport) { | 42 if ($this->haveReadSupport) { |
42 // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. | 43 // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. |
43 // Workaround for this problem is to use temporary files instead of pipes on Windows platform. | 44 // Workaround for this problem is to use temporary files instead of pipes on Windows platform. |
44 // | 45 // |
45 // @see https://bugs.php.net/bug.php?id=51800 | 46 // @see https://bugs.php.net/bug.php?id=51800 |
46 $pipes = array( | 47 $pipes = [ |
47 Process::STDOUT => Process::OUT, | 48 Process::STDOUT => Process::OUT, |
48 Process::STDERR => Process::ERR, | 49 Process::STDERR => Process::ERR, |
49 ); | 50 ]; |
50 $tmpCheck = false; | |
51 $tmpDir = sys_get_temp_dir(); | 51 $tmpDir = sys_get_temp_dir(); |
52 $lastError = 'unknown reason'; | 52 $lastError = 'unknown reason'; |
53 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); | 53 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); |
54 for ($i = 0;; ++$i) { | 54 for ($i = 0;; ++$i) { |
55 foreach ($pipes as $pipe => $name) { | 55 foreach ($pipes as $pipe => $name) { |
56 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); | 56 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); |
57 if (file_exists($file) && !unlink($file)) { | 57 |
58 if (!$h = fopen($file.'.lock', 'w')) { | |
59 restore_error_handler(); | |
60 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $lastError)); | |
61 } | |
62 if (!flock($h, LOCK_EX | LOCK_NB)) { | |
58 continue 2; | 63 continue 2; |
59 } | 64 } |
60 $h = fopen($file, 'xb'); | 65 if (isset($this->lockHandles[$pipe])) { |
61 if (!$h) { | 66 flock($this->lockHandles[$pipe], LOCK_UN); |
62 $error = $lastError; | 67 fclose($this->lockHandles[$pipe]); |
63 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) { | |
64 continue; | |
65 } | |
66 restore_error_handler(); | |
67 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error)); | |
68 } | 68 } |
69 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) { | 69 $this->lockHandles[$pipe] = $h; |
70 | |
71 if (!fclose(fopen($file, 'w')) || !$h = fopen($file, 'r')) { | |
72 flock($this->lockHandles[$pipe], LOCK_UN); | |
73 fclose($this->lockHandles[$pipe]); | |
74 unset($this->lockHandles[$pipe]); | |
70 continue 2; | 75 continue 2; |
71 } | 76 } |
72 if (isset($this->files[$pipe])) { | 77 $this->fileHandles[$pipe] = $h; |
73 unlink($this->files[$pipe]); | |
74 } | |
75 $this->files[$pipe] = $file; | 78 $this->files[$pipe] = $file; |
76 } | 79 } |
77 break; | 80 break; |
78 } | 81 } |
79 restore_error_handler(); | 82 restore_error_handler(); |
83 } | 86 } |
84 | 87 |
85 public function __destruct() | 88 public function __destruct() |
86 { | 89 { |
87 $this->close(); | 90 $this->close(); |
88 $this->removeFiles(); | |
89 } | 91 } |
90 | 92 |
91 /** | 93 /** |
92 * {@inheritdoc} | 94 * {@inheritdoc} |
93 */ | 95 */ |
94 public function getDescriptors() | 96 public function getDescriptors() |
95 { | 97 { |
96 if (!$this->haveReadSupport) { | 98 if (!$this->haveReadSupport) { |
97 $nullstream = fopen('NUL', 'c'); | 99 $nullstream = fopen('NUL', 'c'); |
98 | 100 |
99 return array( | 101 return [ |
100 array('pipe', 'r'), | 102 ['pipe', 'r'], |
101 $nullstream, | 103 $nullstream, |
102 $nullstream, | 104 $nullstream, |
103 ); | 105 ]; |
104 } | 106 } |
105 | 107 |
106 // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) | 108 // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/bug.php?id=51800) |
107 // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 | 109 // We're not using file handles as it can produce corrupted output https://bugs.php.net/bug.php?id=65650 |
108 // So we redirect output within the commandline and pass the nul device to the process | 110 // So we redirect output within the commandline and pass the nul device to the process |
109 return array( | 111 return [ |
110 array('pipe', 'r'), | 112 ['pipe', 'r'], |
111 array('file', 'NUL', 'w'), | 113 ['file', 'NUL', 'w'], |
112 array('file', 'NUL', 'w'), | 114 ['file', 'NUL', 'w'], |
113 ); | 115 ]; |
114 } | 116 } |
115 | 117 |
116 /** | 118 /** |
117 * {@inheritdoc} | 119 * {@inheritdoc} |
118 */ | 120 */ |
126 */ | 128 */ |
127 public function readAndWrite($blocking, $close = false) | 129 public function readAndWrite($blocking, $close = false) |
128 { | 130 { |
129 $this->unblock(); | 131 $this->unblock(); |
130 $w = $this->write(); | 132 $w = $this->write(); |
131 $read = $r = $e = array(); | 133 $read = $r = $e = []; |
132 | 134 |
133 if ($blocking) { | 135 if ($blocking) { |
134 if ($w) { | 136 if ($w) { |
135 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); | 137 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); |
136 } elseif ($this->fileHandles) { | 138 } elseif ($this->fileHandles) { |
139 } | 141 } |
140 foreach ($this->fileHandles as $type => $fileHandle) { | 142 foreach ($this->fileHandles as $type => $fileHandle) { |
141 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]); | 143 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]); |
142 | 144 |
143 if (isset($data[0])) { | 145 if (isset($data[0])) { |
144 $this->readBytes[$type] += strlen($data); | 146 $this->readBytes[$type] += \strlen($data); |
145 $read[$type] = $data; | 147 $read[$type] = $data; |
146 } | 148 } |
147 if ($close) { | 149 if ($close) { |
150 ftruncate($fileHandle, 0); | |
148 fclose($fileHandle); | 151 fclose($fileHandle); |
149 unset($this->fileHandles[$type]); | 152 flock($this->lockHandles[$type], LOCK_UN); |
153 fclose($this->lockHandles[$type]); | |
154 unset($this->fileHandles[$type], $this->lockHandles[$type]); | |
150 } | 155 } |
151 } | 156 } |
152 | 157 |
153 return $read; | 158 return $read; |
154 } | 159 } |
173 * {@inheritdoc} | 178 * {@inheritdoc} |
174 */ | 179 */ |
175 public function close() | 180 public function close() |
176 { | 181 { |
177 parent::close(); | 182 parent::close(); |
178 foreach ($this->fileHandles as $handle) { | 183 foreach ($this->fileHandles as $type => $handle) { |
184 ftruncate($handle, 0); | |
179 fclose($handle); | 185 fclose($handle); |
186 flock($this->lockHandles[$type], LOCK_UN); | |
187 fclose($this->lockHandles[$type]); | |
180 } | 188 } |
181 $this->fileHandles = array(); | 189 $this->fileHandles = $this->lockHandles = []; |
182 } | |
183 | |
184 /** | |
185 * Removes temporary files. | |
186 */ | |
187 private function removeFiles() | |
188 { | |
189 foreach ($this->files as $filename) { | |
190 if (file_exists($filename)) { | |
191 @unlink($filename); | |
192 } | |
193 } | |
194 $this->files = array(); | |
195 } | 190 } |
196 } | 191 } |