Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/process/Process.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | 1fec387a4317 |
children |
comparison
equal
deleted
inserted
replaced
16:c2387f117808 | 17:129ea1e6d783 |
---|---|
56 private $input; | 56 private $input; |
57 private $starttime; | 57 private $starttime; |
58 private $lastOutputTime; | 58 private $lastOutputTime; |
59 private $timeout; | 59 private $timeout; |
60 private $idleTimeout; | 60 private $idleTimeout; |
61 private $options = array('suppress_errors' => true); | 61 private $options = ['suppress_errors' => true]; |
62 private $exitcode; | 62 private $exitcode; |
63 private $fallbackStatus = array(); | 63 private $fallbackStatus = []; |
64 private $processInformation; | 64 private $processInformation; |
65 private $outputDisabled = false; | 65 private $outputDisabled = false; |
66 private $stdout; | 66 private $stdout; |
67 private $stderr; | 67 private $stderr; |
68 private $enhanceWindowsCompatibility = true; | 68 private $enhanceWindowsCompatibility = true; |
86 /** | 86 /** |
87 * Exit codes translation table. | 87 * Exit codes translation table. |
88 * | 88 * |
89 * User-defined errors must use exit codes in the 64-113 range. | 89 * User-defined errors must use exit codes in the 64-113 range. |
90 */ | 90 */ |
91 public static $exitCodes = array( | 91 public static $exitCodes = [ |
92 0 => 'OK', | 92 0 => 'OK', |
93 1 => 'General error', | 93 1 => 'General error', |
94 2 => 'Misuse of shell builtins', | 94 2 => 'Misuse of shell builtins', |
95 | 95 |
96 126 => 'Invoked command cannot execute', | 96 126 => 'Invoked command cannot execute', |
127 155 => 'Profiling timer expired', | 127 155 => 'Profiling timer expired', |
128 // 156 - not defined | 128 // 156 - not defined |
129 157 => 'Pollable event', | 129 157 => 'Pollable event', |
130 // 158 - not defined | 130 // 158 - not defined |
131 159 => 'Bad syscall', | 131 159 => 'Bad syscall', |
132 ); | 132 ]; |
133 | 133 |
134 /** | 134 /** |
135 * @param string|array $commandline The command line to run | 135 * @param string|array $commandline The command line to run |
136 * @param string|null $cwd The working directory or null to use the working dir of the current PHP process | 136 * @param string|null $cwd The working directory or null to use the working dir of the current PHP process |
137 * @param array|null $env The environment variables or null to use the same environment as the current PHP process | 137 * @param array|null $env The environment variables or null to use the same environment as the current PHP process |
141 * | 141 * |
142 * @throws RuntimeException When proc_open is not installed | 142 * @throws RuntimeException When proc_open is not installed |
143 */ | 143 */ |
144 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = null) | 144 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = null) |
145 { | 145 { |
146 if (!function_exists('proc_open')) { | 146 if (!\function_exists('proc_open')) { |
147 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); | 147 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); |
148 } | 148 } |
149 | 149 |
150 $this->commandline = $commandline; | 150 $this->commandline = $commandline; |
151 $this->cwd = $cwd; | 151 $this->cwd = $cwd; |
152 | 152 |
153 // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started | 153 // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started |
154 // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected | 154 // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected |
155 // @see : https://bugs.php.net/bug.php?id=51800 | 155 // @see : https://bugs.php.net/bug.php?id=51800 |
156 // @see : https://bugs.php.net/bug.php?id=50524 | 156 // @see : https://bugs.php.net/bug.php?id=50524 |
157 if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) { | 157 if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) { |
158 $this->cwd = getcwd(); | 158 $this->cwd = getcwd(); |
159 } | 159 } |
160 if (null !== $env) { | 160 if (null !== $env) { |
161 $this->setEnv($env); | 161 $this->setEnv($env); |
162 } | 162 } |
163 | 163 |
164 $this->setInput($input); | 164 $this->setInput($input); |
165 $this->setTimeout($timeout); | 165 $this->setTimeout($timeout); |
166 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR; | 166 $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR; |
167 $this->pty = false; | 167 $this->pty = false; |
168 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled(); | 168 $this->enhanceSigchildCompatibility = '\\' !== \DIRECTORY_SEPARATOR && $this->isSigchildEnabled(); |
169 if (null !== $options) { | 169 if (null !== $options) { |
170 @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); | 170 @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); |
171 $this->options = array_replace($this->options, $options); | 171 $this->options = array_replace($this->options, $options); |
172 } | 172 } |
173 } | 173 } |
202 * @throws RuntimeException When process stopped after receiving signal | 202 * @throws RuntimeException When process stopped after receiving signal |
203 * @throws LogicException In case a callback is provided and output has been disabled | 203 * @throws LogicException In case a callback is provided and output has been disabled |
204 * | 204 * |
205 * @final since version 3.3 | 205 * @final since version 3.3 |
206 */ | 206 */ |
207 public function run($callback = null/*, array $env = array()*/) | 207 public function run($callback = null/*, array $env = []*/) |
208 { | 208 { |
209 $env = 1 < func_num_args() ? func_get_arg(1) : null; | 209 $env = 1 < \func_num_args() ? func_get_arg(1) : null; |
210 $this->start($callback, $env); | 210 $this->start($callback, $env); |
211 | 211 |
212 return $this->wait(); | 212 return $this->wait(); |
213 } | 213 } |
214 | 214 |
226 * @throws RuntimeException if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled | 226 * @throws RuntimeException if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled |
227 * @throws ProcessFailedException if the process didn't terminate successfully | 227 * @throws ProcessFailedException if the process didn't terminate successfully |
228 * | 228 * |
229 * @final since version 3.3 | 229 * @final since version 3.3 |
230 */ | 230 */ |
231 public function mustRun(callable $callback = null/*, array $env = array()*/) | 231 public function mustRun(callable $callback = null/*, array $env = []*/) |
232 { | 232 { |
233 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { | 233 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { |
234 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); | 234 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); |
235 } | 235 } |
236 $env = 1 < func_num_args() ? func_get_arg(1) : null; | 236 $env = 1 < \func_num_args() ? func_get_arg(1) : null; |
237 | 237 |
238 if (0 !== $this->run($callback, $env)) { | 238 if (0 !== $this->run($callback, $env)) { |
239 throw new ProcessFailedException($this); | 239 throw new ProcessFailedException($this); |
240 } | 240 } |
241 | 241 |
260 * | 260 * |
261 * @throws RuntimeException When process can't be launched | 261 * @throws RuntimeException When process can't be launched |
262 * @throws RuntimeException When process is already running | 262 * @throws RuntimeException When process is already running |
263 * @throws LogicException In case a callback is provided and output has been disabled | 263 * @throws LogicException In case a callback is provided and output has been disabled |
264 */ | 264 */ |
265 public function start(callable $callback = null/*, array $env = array()*/) | 265 public function start(callable $callback = null/*, array $env = [*/) |
266 { | 266 { |
267 if ($this->isRunning()) { | 267 if ($this->isRunning()) { |
268 throw new RuntimeException('Process is already running'); | 268 throw new RuntimeException('Process is already running'); |
269 } | 269 } |
270 if (2 <= func_num_args()) { | 270 if (2 <= \func_num_args()) { |
271 $env = func_get_arg(1); | 271 $env = func_get_arg(1); |
272 } else { | 272 } else { |
273 if (__CLASS__ !== static::class) { | 273 if (__CLASS__ !== static::class) { |
274 $r = new \ReflectionMethod($this, __FUNCTION__); | 274 $r = new \ReflectionMethod($this, __FUNCTION__); |
275 if (__CLASS__ !== $r->getDeclaringClass()->getName() && (2 > $r->getNumberOfParameters() || 'env' !== $r->getParameters()[0]->name)) { | 275 if (__CLASS__ !== $r->getDeclaringClass()->getName() && (2 > $r->getNumberOfParameters() || 'env' !== $r->getParameters()[1]->name)) { |
276 @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED); | 276 @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED); |
277 } | 277 } |
278 } | 278 } |
279 $env = null; | 279 $env = null; |
280 } | 280 } |
284 $this->callback = $this->buildCallback($callback); | 284 $this->callback = $this->buildCallback($callback); |
285 $this->hasCallback = null !== $callback; | 285 $this->hasCallback = null !== $callback; |
286 $descriptors = $this->getDescriptors(); | 286 $descriptors = $this->getDescriptors(); |
287 $inheritEnv = $this->inheritEnv; | 287 $inheritEnv = $this->inheritEnv; |
288 | 288 |
289 if (is_array($commandline = $this->commandline)) { | 289 if (\is_array($commandline = $this->commandline)) { |
290 $commandline = implode(' ', array_map(array($this, 'escapeArgument'), $commandline)); | 290 $commandline = implode(' ', array_map([$this, 'escapeArgument'], $commandline)); |
291 | 291 |
292 if ('\\' !== DIRECTORY_SEPARATOR) { | 292 if ('\\' !== \DIRECTORY_SEPARATOR) { |
293 // exec is mandatory to deal with sending a signal to the process | 293 // exec is mandatory to deal with sending a signal to the process |
294 $commandline = 'exec '.$commandline; | 294 $commandline = 'exec '.$commandline; |
295 } | 295 } |
296 } | 296 } |
297 | 297 |
309 } elseif (null !== $env) { | 309 } elseif (null !== $env) { |
310 @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED); | 310 @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED); |
311 } else { | 311 } else { |
312 $env = $this->getDefaultEnv(); | 312 $env = $this->getDefaultEnv(); |
313 } | 313 } |
314 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { | 314 if ('\\' === \DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { |
315 $this->options['bypass_shell'] = true; | 315 $this->options['bypass_shell'] = true; |
316 $commandline = $this->prepareWindowsCommandLine($commandline, $env); | 316 $commandline = $this->prepareWindowsCommandLine($commandline, $env); |
317 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { | 317 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { |
318 // last exit code is output on the fourth pipe and caught to work around --enable-sigchild | 318 // last exit code is output on the fourth pipe and caught to work around --enable-sigchild |
319 $descriptors[3] = array('pipe', 'w'); | 319 $descriptors[3] = ['pipe', 'w']; |
320 | 320 |
321 // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input | 321 // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input |
322 $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; | 322 $commandline = '{ ('.$commandline.') <&3 3<&- 3>/dev/null & } 3<&0;'; |
323 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code'; | 323 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code'; |
324 | 324 |
325 // Workaround for the bug, when PTS functionality is enabled. | 325 // Workaround for the bug, when PTS functionality is enabled. |
326 // @see : https://bugs.php.net/69442 | 326 // @see : https://bugs.php.net/69442 |
327 $ptsWorkaround = fopen(__FILE__, 'r'); | 327 $ptsWorkaround = fopen(__FILE__, 'r'); |
328 } | 328 } |
329 if (defined('HHVM_VERSION')) { | 329 if (\defined('HHVM_VERSION')) { |
330 $envPairs = $env; | 330 $envPairs = $env; |
331 } else { | 331 } else { |
332 $envPairs = array(); | 332 $envPairs = []; |
333 foreach ($env as $k => $v) { | 333 foreach ($env as $k => $v) { |
334 if (false !== $v) { | 334 if (false !== $v) { |
335 $envPairs[] = $k.'='.$v; | 335 $envPairs[] = $k.'='.$v; |
336 } | 336 } |
337 } | 337 } |
341 @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); | 341 @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); |
342 } | 342 } |
343 | 343 |
344 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); | 344 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options); |
345 | 345 |
346 if (!is_resource($this->process)) { | 346 if (!\is_resource($this->process)) { |
347 throw new RuntimeException('Unable to launch a new process.'); | 347 throw new RuntimeException('Unable to launch a new process.'); |
348 } | 348 } |
349 $this->status = self::STATUS_STARTED; | 349 $this->status = self::STATUS_STARTED; |
350 | 350 |
351 if (isset($descriptors[3])) { | 351 if (isset($descriptors[3])) { |
376 * | 376 * |
377 * @see start() | 377 * @see start() |
378 * | 378 * |
379 * @final since version 3.3 | 379 * @final since version 3.3 |
380 */ | 380 */ |
381 public function restart(callable $callback = null/*, array $env = array()*/) | 381 public function restart(callable $callback = null/*, array $env = []*/) |
382 { | 382 { |
383 if ($this->isRunning()) { | 383 if ($this->isRunning()) { |
384 throw new RuntimeException('Process is already running'); | 384 throw new RuntimeException('Process is already running'); |
385 } | 385 } |
386 $env = 1 < func_num_args() ? func_get_arg(1) : null; | 386 $env = 1 < \func_num_args() ? func_get_arg(1) : null; |
387 | 387 |
388 $process = clone $this; | 388 $process = clone $this; |
389 $process->start($callback, $env); | 389 $process->start($callback, $env); |
390 | 390 |
391 return $process; | 391 return $process; |
420 $this->callback = $this->buildCallback($callback); | 420 $this->callback = $this->buildCallback($callback); |
421 } | 421 } |
422 | 422 |
423 do { | 423 do { |
424 $this->checkTimeout(); | 424 $this->checkTimeout(); |
425 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); | 425 $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen(); |
426 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running); | 426 $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running); |
427 } while ($running); | 427 } while ($running); |
428 | 428 |
429 while ($this->isRunning()) { | 429 while ($this->isRunning()) { |
430 usleep(1000); | 430 usleep(1000); |
431 } | 431 } |
690 } | 690 } |
691 | 691 |
692 /** | 692 /** |
693 * Returns the exit code returned by the process. | 693 * Returns the exit code returned by the process. |
694 * | 694 * |
695 * @return null|int The exit status code, null if the Process is not terminated | 695 * @return int|null The exit status code, null if the Process is not terminated |
696 * | 696 * |
697 * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled | 697 * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled |
698 */ | 698 */ |
699 public function getExitCode() | 699 public function getExitCode() |
700 { | 700 { |
711 * Returns a string representation for the exit code returned by the process. | 711 * Returns a string representation for the exit code returned by the process. |
712 * | 712 * |
713 * This method relies on the Unix exit code status standardization | 713 * This method relies on the Unix exit code status standardization |
714 * and might not be relevant for other operating systems. | 714 * and might not be relevant for other operating systems. |
715 * | 715 * |
716 * @return null|string A string representation for the exit status code, null if the Process is not terminated | 716 * @return string|null A string representation for the exit status code, null if the Process is not terminated |
717 * | 717 * |
718 * @see http://tldp.org/LDP/abs/html/exitcodes.html | 718 * @see http://tldp.org/LDP/abs/html/exitcodes.html |
719 * @see http://en.wikipedia.org/wiki/Unix_signal | 719 * @see http://en.wikipedia.org/wiki/Unix_signal |
720 */ | 720 */ |
721 public function getExitCodeText() | 721 public function getExitCodeText() |
937 * | 937 * |
938 * @return string The command to execute | 938 * @return string The command to execute |
939 */ | 939 */ |
940 public function getCommandLine() | 940 public function getCommandLine() |
941 { | 941 { |
942 return is_array($this->commandline) ? implode(' ', array_map(array($this, 'escapeArgument'), $this->commandline)) : $this->commandline; | 942 return \is_array($this->commandline) ? implode(' ', array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline; |
943 } | 943 } |
944 | 944 |
945 /** | 945 /** |
946 * Sets the command line to be executed. | 946 * Sets the command line to be executed. |
947 * | 947 * |
1026 * | 1026 * |
1027 * @throws RuntimeException In case the TTY mode is not supported | 1027 * @throws RuntimeException In case the TTY mode is not supported |
1028 */ | 1028 */ |
1029 public function setTty($tty) | 1029 public function setTty($tty) |
1030 { | 1030 { |
1031 if ('\\' === DIRECTORY_SEPARATOR && $tty) { | 1031 if ('\\' === \DIRECTORY_SEPARATOR && $tty) { |
1032 throw new RuntimeException('TTY mode is not supported on Windows platform.'); | 1032 throw new RuntimeException('TTY mode is not supported on Windows platform.'); |
1033 } | 1033 } |
1034 if ($tty) { | 1034 if ($tty) { |
1035 static $isTtySupported; | 1035 static $isTtySupported; |
1036 | 1036 |
1037 if (null === $isTtySupported) { | 1037 if (null === $isTtySupported) { |
1038 $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', array(array('file', '/dev/tty', 'r'), array('file', '/dev/tty', 'w'), array('file', '/dev/tty', 'w')), $pipes); | 1038 $isTtySupported = (bool) @proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes); |
1039 } | 1039 } |
1040 | 1040 |
1041 if (!$isTtySupported) { | 1041 if (!$isTtySupported) { |
1042 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); | 1042 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.'); |
1043 } | 1043 } |
1139 */ | 1139 */ |
1140 public function setEnv(array $env) | 1140 public function setEnv(array $env) |
1141 { | 1141 { |
1142 // Process can not handle env values that are arrays | 1142 // Process can not handle env values that are arrays |
1143 $env = array_filter($env, function ($value) { | 1143 $env = array_filter($env, function ($value) { |
1144 return !is_array($value); | 1144 return !\is_array($value); |
1145 }); | 1145 }); |
1146 | 1146 |
1147 $this->env = $env; | 1147 $this->env = $env; |
1148 | 1148 |
1149 return $this; | 1149 return $this; |
1353 | 1353 |
1354 if (null !== $result) { | 1354 if (null !== $result) { |
1355 return $result; | 1355 return $result; |
1356 } | 1356 } |
1357 | 1357 |
1358 if ('\\' === DIRECTORY_SEPARATOR) { | 1358 if ('\\' === \DIRECTORY_SEPARATOR) { |
1359 return $result = false; | 1359 return $result = false; |
1360 } | 1360 } |
1361 | 1361 |
1362 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes); | 1362 return $result = (bool) @proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes); |
1363 } | 1363 } |
1364 | 1364 |
1365 /** | 1365 /** |
1366 * Creates the descriptors needed by the proc_open. | 1366 * Creates the descriptors needed by the proc_open. |
1367 * | 1367 * |
1370 private function getDescriptors() | 1370 private function getDescriptors() |
1371 { | 1371 { |
1372 if ($this->input instanceof \Iterator) { | 1372 if ($this->input instanceof \Iterator) { |
1373 $this->input->rewind(); | 1373 $this->input->rewind(); |
1374 } | 1374 } |
1375 if ('\\' === DIRECTORY_SEPARATOR) { | 1375 if ('\\' === \DIRECTORY_SEPARATOR) { |
1376 $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback); | 1376 $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback); |
1377 } else { | 1377 } else { |
1378 $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback); | 1378 $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback); |
1379 } | 1379 } |
1380 | 1380 |
1394 protected function buildCallback(callable $callback = null) | 1394 protected function buildCallback(callable $callback = null) |
1395 { | 1395 { |
1396 if ($this->outputDisabled) { | 1396 if ($this->outputDisabled) { |
1397 return function ($type, $data) use ($callback) { | 1397 return function ($type, $data) use ($callback) { |
1398 if (null !== $callback) { | 1398 if (null !== $callback) { |
1399 call_user_func($callback, $type, $data); | 1399 \call_user_func($callback, $type, $data); |
1400 } | 1400 } |
1401 }; | 1401 }; |
1402 } | 1402 } |
1403 | 1403 |
1404 $out = self::OUT; | 1404 $out = self::OUT; |
1409 } else { | 1409 } else { |
1410 $this->addErrorOutput($data); | 1410 $this->addErrorOutput($data); |
1411 } | 1411 } |
1412 | 1412 |
1413 if (null !== $callback) { | 1413 if (null !== $callback) { |
1414 call_user_func($callback, $type, $data); | 1414 \call_user_func($callback, $type, $data); |
1415 } | 1415 } |
1416 }; | 1416 }; |
1417 } | 1417 } |
1418 | 1418 |
1419 /** | 1419 /** |
1428 } | 1428 } |
1429 | 1429 |
1430 $this->processInformation = proc_get_status($this->process); | 1430 $this->processInformation = proc_get_status($this->process); |
1431 $running = $this->processInformation['running']; | 1431 $running = $this->processInformation['running']; |
1432 | 1432 |
1433 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running); | 1433 $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running); |
1434 | 1434 |
1435 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { | 1435 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { |
1436 $this->processInformation = $this->fallbackStatus + $this->processInformation; | 1436 $this->processInformation = $this->fallbackStatus + $this->processInformation; |
1437 } | 1437 } |
1438 | 1438 |
1450 { | 1450 { |
1451 if (null !== self::$sigchild) { | 1451 if (null !== self::$sigchild) { |
1452 return self::$sigchild; | 1452 return self::$sigchild; |
1453 } | 1453 } |
1454 | 1454 |
1455 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) { | 1455 if (!\function_exists('phpinfo') || \defined('HHVM_VERSION')) { |
1456 return self::$sigchild = false; | 1456 return self::$sigchild = false; |
1457 } | 1457 } |
1458 | 1458 |
1459 ob_start(); | 1459 ob_start(); |
1460 phpinfo(INFO_GENERAL); | 1460 phpinfo(INFO_GENERAL); |
1529 * @return int The exitcode | 1529 * @return int The exitcode |
1530 */ | 1530 */ |
1531 private function close() | 1531 private function close() |
1532 { | 1532 { |
1533 $this->processPipes->close(); | 1533 $this->processPipes->close(); |
1534 if (is_resource($this->process)) { | 1534 if (\is_resource($this->process)) { |
1535 proc_close($this->process); | 1535 proc_close($this->process); |
1536 } | 1536 } |
1537 $this->exitcode = $this->processInformation['exitcode']; | 1537 $this->exitcode = $this->processInformation['exitcode']; |
1538 $this->status = self::STATUS_TERMINATED; | 1538 $this->status = self::STATUS_TERMINATED; |
1539 | 1539 |
1561 private function resetProcessData() | 1561 private function resetProcessData() |
1562 { | 1562 { |
1563 $this->starttime = null; | 1563 $this->starttime = null; |
1564 $this->callback = null; | 1564 $this->callback = null; |
1565 $this->exitcode = null; | 1565 $this->exitcode = null; |
1566 $this->fallbackStatus = array(); | 1566 $this->fallbackStatus = []; |
1567 $this->processInformation = null; | 1567 $this->processInformation = null; |
1568 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+'); | 1568 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b'); |
1569 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+'); | 1569 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'w+b'); |
1570 $this->process = null; | 1570 $this->process = null; |
1571 $this->latestSignal = null; | 1571 $this->latestSignal = null; |
1572 $this->status = self::STATUS_READY; | 1572 $this->status = self::STATUS_READY; |
1573 $this->incrementalOutputOffset = 0; | 1573 $this->incrementalOutputOffset = 0; |
1574 $this->incrementalErrorOutputOffset = 0; | 1574 $this->incrementalErrorOutputOffset = 0; |
1594 } | 1594 } |
1595 | 1595 |
1596 return false; | 1596 return false; |
1597 } | 1597 } |
1598 | 1598 |
1599 if ('\\' === DIRECTORY_SEPARATOR) { | 1599 if ('\\' === \DIRECTORY_SEPARATOR) { |
1600 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode); | 1600 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode); |
1601 if ($exitCode && $this->isRunning()) { | 1601 if ($exitCode && $this->isRunning()) { |
1602 if ($throwException) { | 1602 if ($throwException) { |
1603 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output))); | 1603 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output))); |
1604 } | 1604 } |
1606 return false; | 1606 return false; |
1607 } | 1607 } |
1608 } else { | 1608 } else { |
1609 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) { | 1609 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) { |
1610 $ok = @proc_terminate($this->process, $signal); | 1610 $ok = @proc_terminate($this->process, $signal); |
1611 } elseif (function_exists('posix_kill')) { | 1611 } elseif (\function_exists('posix_kill')) { |
1612 $ok = @posix_kill($pid, $signal); | 1612 $ok = @posix_kill($pid, $signal); |
1613 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) { | 1613 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) { |
1614 $ok = false === fgets($pipes[2]); | 1614 $ok = false === fgets($pipes[2]); |
1615 } | 1615 } |
1616 if (!$ok) { | 1616 if (!$ok) { |
1617 if ($throwException) { | 1617 if ($throwException) { |
1618 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); | 1618 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal)); |
1632 | 1632 |
1633 private function prepareWindowsCommandLine($cmd, array &$env) | 1633 private function prepareWindowsCommandLine($cmd, array &$env) |
1634 { | 1634 { |
1635 $uid = uniqid('', true); | 1635 $uid = uniqid('', true); |
1636 $varCount = 0; | 1636 $varCount = 0; |
1637 $varCache = array(); | 1637 $varCache = []; |
1638 $cmd = preg_replace_callback( | 1638 $cmd = preg_replace_callback( |
1639 '/"(?:( | 1639 '/"(?:( |
1640 [^"%!^]*+ | 1640 [^"%!^]*+ |
1641 (?: | 1641 (?: |
1642 (?: !LF! | "(?:\^[%!^])?+" ) | 1642 (?: !LF! | "(?:\^[%!^])?+" ) |
1655 } | 1655 } |
1656 if (false === strpbrk($value, "\"%!\n")) { | 1656 if (false === strpbrk($value, "\"%!\n")) { |
1657 return '"'.$value.'"'; | 1657 return '"'.$value.'"'; |
1658 } | 1658 } |
1659 | 1659 |
1660 $value = str_replace(array('!LF!', '"^!"', '"^%"', '"^^"', '""'), array("\n", '!', '%', '^', '"'), $value); | 1660 $value = str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value); |
1661 $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"'; | 1661 $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"'; |
1662 $var = $uid.++$varCount; | 1662 $var = $uid.++$varCount; |
1663 | 1663 |
1664 $env[$var] = $value; | 1664 $env[$var] = $value; |
1665 | 1665 |
1711 * | 1711 * |
1712 * @return string The escaped argument | 1712 * @return string The escaped argument |
1713 */ | 1713 */ |
1714 private function escapeArgument($argument) | 1714 private function escapeArgument($argument) |
1715 { | 1715 { |
1716 if ('\\' !== DIRECTORY_SEPARATOR) { | 1716 if ('\\' !== \DIRECTORY_SEPARATOR) { |
1717 return "'".str_replace("'", "'\\''", $argument)."'"; | 1717 return "'".str_replace("'", "'\\''", $argument)."'"; |
1718 } | 1718 } |
1719 if ('' === $argument = (string) $argument) { | 1719 if ('' === $argument = (string) $argument) { |
1720 return '""'; | 1720 return '""'; |
1721 } | 1721 } |
1725 if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { | 1725 if (!preg_match('/[\/()%!^"<>&|\s]/', $argument)) { |
1726 return $argument; | 1726 return $argument; |
1727 } | 1727 } |
1728 $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); | 1728 $argument = preg_replace('/(\\\\+)$/', '$1$1', $argument); |
1729 | 1729 |
1730 return '"'.str_replace(array('"', '^', '%', '!', "\n"), array('""', '"^^"', '"^%"', '"^!"', '!LF!'), $argument).'"'; | 1730 return '"'.str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument).'"'; |
1731 } | 1731 } |
1732 | 1732 |
1733 private function getDefaultEnv() | 1733 private function getDefaultEnv() |
1734 { | 1734 { |
1735 $env = array(); | 1735 $env = []; |
1736 | 1736 |
1737 foreach ($_SERVER as $k => $v) { | 1737 foreach ($_SERVER as $k => $v) { |
1738 if (is_string($v) && false !== $v = getenv($k)) { | 1738 if (\is_string($v) && false !== $v = getenv($k)) { |
1739 $env[$k] = $v; | 1739 $env[$k] = $v; |
1740 } | 1740 } |
1741 } | 1741 } |
1742 | 1742 |
1743 foreach ($_ENV as $k => $v) { | 1743 foreach ($_ENV as $k => $v) { |
1744 if (is_string($v)) { | 1744 if (\is_string($v)) { |
1745 $env[$k] = $v; | 1745 $env[$k] = $v; |
1746 } | 1746 } |
1747 } | 1747 } |
1748 | 1748 |
1749 return $env; | 1749 return $env; |