PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 5.7.0
Defender Security – Malware Scanner, Login Security & Firewall v5.7.0
6.3.0 6.2.3 6.2.4 6.2.0 6.2.1 6.2.2 6.1.0 5.3.1 5.4.0 5.4.1 5.5.0 5.5.1 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.7.2 5.8.0 5.8.1 5.9.0 6.0.0 6.0.1 3.0.1 3.1.0 All 141 releases
defender-security / vendor / symfony / process / Pipes / WindowsPipes.php

WindowsPipes.php in Defender Security – Malware Scanner, Login Security & Firewall 5.7.0, at vendor/symfony/process/Pipes/WindowsPipes.php

205 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <[email protected]>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\Process\Pipes;
13
14 use Symfony\Component\Process\Exception\RuntimeException;
15 use Symfony\Component\Process\Process;
16
17 /**
18 * WindowsPipes implementation uses temporary files as handles.
19 *
20 * @see https://bugs.php.net/51800
21 * @see https://bugs.php.net/65650
22 *
23 * @author Romain Neutron <[email protected]>
24 *
25 * @internal
26 */
27 class WindowsPipes extends AbstractPipes
28 {
29 private $files = [];
30 private $fileHandles = [];
31 private $lockHandles = [];
32 private $readBytes = [
33 Process::STDOUT => 0,
34 Process::STDERR => 0,
35 ];
36 private $haveReadSupport;
37
38 public function __construct($input, bool $haveReadSupport)
39 {
40 $this->haveReadSupport = $haveReadSupport;
41
42 if ($this->haveReadSupport) {
43 // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
44 // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
45 //
46 // @see https://bugs.php.net/51800
47 $pipes = [
48 Process::STDOUT => Process::OUT,
49 Process::STDERR => Process::ERR,
50 ];
51 $tmpDir = sys_get_temp_dir();
52 $lastError = 'unknown reason';
53 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
54 for ($i = 0;; ++$i) {
55 foreach ($pipes as $pipe => $name) {
56 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
57
58 if (!$h = fopen($file.'.lock', 'w')) {
59 if (file_exists($file.'.lock')) {
60 continue 2;
61 }
62 restore_error_handler();
63 throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError);
64 }
65 if (!flock($h, \LOCK_EX | \LOCK_NB)) {
66 continue 2;
67 }
68 if (isset($this->lockHandles[$pipe])) {
69 flock($this->lockHandles[$pipe], \LOCK_UN);
70 fclose($this->lockHandles[$pipe]);
71 }
72 $this->lockHandles[$pipe] = $h;
73
74 if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) {
75 flock($this->lockHandles[$pipe], \LOCK_UN);
76 fclose($this->lockHandles[$pipe]);
77 unset($this->lockHandles[$pipe]);
78 continue 2;
79 }
80 $this->fileHandles[$pipe] = $h;
81 $this->files[$pipe] = $file;
82 }
83 break;
84 }
85 restore_error_handler();
86 }
87
88 parent::__construct($input);
89 }
90
91 public function __sleep(): array
92 {
93 throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
94 }
95
96 public function __wakeup()
97 {
98 throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
99 }
100
101 public function __destruct()
102 {
103 $this->close();
104 }
105
106 /**
107 * {@inheritdoc}
108 */
109 public function getDescriptors(): array
110 {
111 if (!$this->haveReadSupport) {
112 $nullstream = fopen('NUL', 'c');
113
114 return [
115 ['pipe', 'r'],
116 $nullstream,
117 $nullstream,
118 ];
119 }
120
121 // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
122 // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
123 // So we redirect output within the commandline and pass the nul device to the process
124 return [
125 ['pipe', 'r'],
126 ['file', 'NUL', 'w'],
127 ['file', 'NUL', 'w'],
128 ];
129 }
130
131 /**
132 * {@inheritdoc}
133 */
134 public function getFiles(): array
135 {
136 return $this->files;
137 }
138
139 /**
140 * {@inheritdoc}
141 */
142 public function readAndWrite(bool $blocking, bool $close = false): array
143 {
144 $this->unblock();
145 $w = $this->write();
146 $read = $r = $e = [];
147
148 if ($blocking) {
149 if ($w) {
150 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
151 } elseif ($this->fileHandles) {
152 usleep((int) (Process::TIMEOUT_PRECISION * 1E6));
153 }
154 }
155 foreach ($this->fileHandles as $type => $fileHandle) {
156 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
157
158 if (isset($data[0])) {
159 $this->readBytes[$type] += \strlen($data);
160 $read[$type] = $data;
161 }
162 if ($close) {
163 ftruncate($fileHandle, 0);
164 fclose($fileHandle);
165 flock($this->lockHandles[$type], \LOCK_UN);
166 fclose($this->lockHandles[$type]);
167 unset($this->fileHandles[$type], $this->lockHandles[$type]);
168 }
169 }
170
171 return $read;
172 }
173
174 /**
175 * {@inheritdoc}
176 */
177 public function haveReadSupport(): bool
178 {
179 return $this->haveReadSupport;
180 }
181
182 /**
183 * {@inheritdoc}
184 */
185 public function areOpen(): bool
186 {
187 return $this->pipes && $this->fileHandles;
188 }
189
190 /**
191 * {@inheritdoc}
192 */
193 public function close()
194 {
195 parent::close();
196 foreach ($this->fileHandles as $type => $handle) {
197 ftruncate($handle, 0);
198 fclose($handle);
199 flock($this->lockHandles[$type], \LOCK_UN);
200 fclose($this->lockHandles[$type]);
201 }
202 $this->fileHandles = $this->lockHandles = [];
203 }
204 }
205