PluginProbe
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell / 3.13.3
WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell v3.13.3
3.13.3 3.13.2 3.13.1 3.13.0 3.12.13 3.12.12 3.12.11 3.12.10 3.12.9 3.12.8 3.12.7 3.12.6 3.12.5 3.12.4 3.12.3 3.12.1 3.12.2 3.12.0 3.11.1 3.11.0 3.10.9 3.10.8 3.10.7 3.10.6 2.8.16 All 261 releases
wpfunnels / vendor / symfony / process / Pipes / WindowsPipes.php

WindowsPipes.php in WPFunnels – Funnel Builder for WooCommerce with Checkout & One Click Upsell 3.13.3, at vendor/symfony/process/Pipes/WindowsPipes.php

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