PluginProbe
Defender Security – Malware Scanner, Login Security & Firewall / 3.0.1
Defender Security – Malware Scanner, Login Security & Firewall v3.0.1
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 3.0.1, at vendor/symfony/process/Pipes/WindowsPipes.php

208 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 /**
92 * @return array
93 */
94 public function __sleep()
95 {
96 throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
97 }
98
99 public function __wakeup()
100 {
101 throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
102 }
103
104 public function __destruct()
105 {
106 $this->close();
107 }
108
109 /**
110 * {@inheritdoc}
111 */
112 public function getDescriptors(): array
113 {
114 if (!$this->haveReadSupport) {
115 $nullstream = fopen('NUL', 'c');
116
117 return [
118 ['pipe', 'r'],
119 $nullstream,
120 $nullstream,
121 ];
122 }
123
124 // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
125 // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
126 // So we redirect output within the commandline and pass the nul device to the process
127 return [
128 ['pipe', 'r'],
129 ['file', 'NUL', 'w'],
130 ['file', 'NUL', 'w'],
131 ];
132 }
133
134 /**
135 * {@inheritdoc}
136 */
137 public function getFiles(): array
138 {
139 return $this->files;
140 }
141
142 /**
143 * {@inheritdoc}
144 */
145 public function readAndWrite(bool $blocking, bool $close = false): array
146 {
147 $this->unblock();
148 $w = $this->write();
149 $read = $r = $e = [];
150
151 if ($blocking) {
152 if ($w) {
153 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
154 } elseif ($this->fileHandles) {
155 usleep(Process::TIMEOUT_PRECISION * 1E6);
156 }
157 }
158 foreach ($this->fileHandles as $type => $fileHandle) {
159 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
160
161 if (isset($data[0])) {
162 $this->readBytes[$type] += \strlen($data);
163 $read[$type] = $data;
164 }
165 if ($close) {
166 ftruncate($fileHandle, 0);
167 fclose($fileHandle);
168 flock($this->lockHandles[$type], \LOCK_UN);
169 fclose($this->lockHandles[$type]);
170 unset($this->fileHandles[$type], $this->lockHandles[$type]);
171 }
172 }
173
174 return $read;
175 }
176
177 /**
178 * {@inheritdoc}
179 */
180 public function haveReadSupport(): bool
181 {
182 return $this->haveReadSupport;
183 }
184
185 /**
186 * {@inheritdoc}
187 */
188 public function areOpen(): bool
189 {
190 return $this->pipes && $this->fileHandles;
191 }
192
193 /**
194 * {@inheritdoc}
195 */
196 public function close()
197 {
198 parent::close();
199 foreach ($this->fileHandles as $type => $handle) {
200 ftruncate($handle, 0);
201 fclose($handle);
202 flock($this->lockHandles[$type], \LOCK_UN);
203 fclose($this->lockHandles[$type]);
204 }
205 $this->fileHandles = $this->lockHandles = [];
206 }
207 }
208