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;