Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f253d62

Browse files
Merge branch '2.3' into 2.7
* 2.3: [Process] Enhance compatiblity with --enable-sigchild [Process] Always call proc_close [Validator] Updated Luxembourgish translations for 2.8 [FrameworkBundle] prevent cache:clear creating too long paths Conflicts: src/Symfony/Component/Process/Tests/ProcessTest.php src/Symfony/Component/Process/Tests/SigchildDisabledProcessTest.php src/Symfony/Component/Process/Tests/SigchildEnabledProcessTest.php src/Symfony/Component/Process/Tests/SimpleProcessTest.php src/Symfony/Component/Validator/Resources/translations/validators.lb.xlf
2 parents 447ea79 + 423f83f commit f253d62

File tree

10 files changed

+238
-772
lines changed

10 files changed

+238
-772
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ addons:
1010
cache:
1111
directories:
1212
- .phpunit
13+
- php-5.3.9
1314

1415
matrix:
1516
include:
@@ -32,6 +33,7 @@ env:
3233

3334
before_install:
3435
- if [[ "$deps" = "no" ]] && [[ "$TRAVIS_PHP_VERSION" =~ 5.[45] ]] && [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then export deps=skip; fi;
36+
- if [[ $deps = no && $TRAVIS_PHP_VERSION = 5.3 && ! -d php-5.3.9/sapi ]]; then wget http://museum.php.net/php5/php-5.3.9.tar.bz2; tar -xjf php-5.3.9.tar.bz2; (cd php-5.3.9; ./configure --enable-sigchild --enable-pcntl; make -j2); fi;
3537
- if [[ "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi;
3638
- echo "memory_limit = -1" >> $INI_FILE
3739
- echo "session.gc_probability = 0" >> $INI_FILE
@@ -56,6 +58,7 @@ install:
5658
script:
5759
- if [ "$deps" = "no" ]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi;
5860
- if [ "$deps" = "no" ]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi;
61+
- if [[ $deps = no && $TRAVIS_PHP_VERSION = 5.3 ]]; then echo -e "1\\n0" | parallel --gnu 'echo -e "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-5.3.9/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi;
5962
- if [ "$deps" = "high" ]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer --prefer-source update; $PHPUNIT --exclude-group tty,benchmark,intl-data'; fi;
6063
- if [ "$deps" = "low" ]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer --prefer-source --prefer-lowest --prefer-stable update; $PHPUNIT --exclude-group tty,benchmark,intl-data'; fi;
6164
- if [ "$deps" = "skip" ]; then echo 'This matrix line is skipped for pull requests.'; fi;

src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ protected function configure()
5454
protected function execute(InputInterface $input, OutputInterface $output)
5555
{
5656
$realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
57-
$oldCacheDir = $realCacheDir.'_old';
57+
// the old cache dir name must not be longer than the real one to avoid exceeding
58+
// the maximum length of a directory or file path within it (esp. Windows MAX_PATH)
59+
$oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~');
5860
$filesystem = $this->getContainer()->get('filesystem');
5961

6062
if (!is_writable($realCacheDir)) {
@@ -75,7 +77,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
7577
// the warmup cache dir name must have the same length than the real one
7678
// to avoid the many problems in serialized resources files
7779
$realCacheDir = realpath($realCacheDir);
78-
$warmupDir = substr($realCacheDir, 0, -1).'_';
80+
$warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_');
7981

8082
if ($filesystem->exists($warmupDir)) {
8183
if ($output->isVerbose()) {
@@ -114,8 +116,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
114116
*/
115117
protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = true)
116118
{
117-
$this->getContainer()->get('filesystem')->remove($warmupDir);
118-
119119
// create a temporary kernel
120120
$realKernel = $this->getContainer()->get('kernel');
121121
$realKernelClass = get_class($realKernel);

src/Symfony/Component/Process/Process.php

Lines changed: 65 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Process
5454
private $idleTimeout;
5555
private $options;
5656
private $exitcode;
57-
private $fallbackExitcode;
57+
private $fallbackStatus = array();
5858
private $processInformation;
5959
private $outputDisabled = false;
6060
private $stdout;
@@ -75,6 +75,14 @@ class Process
7575
private $latestSignal;
7676

7777
private static $sigchild;
78+
private static $posixSignals = array(
79+
1 => 1, // SIGHUP
80+
2 => 2, // SIGINT
81+
3 => 3, // SIGQUIT
82+
6 => 6, // SIGABRT
83+
14 => 14, // SIGALRM
84+
15 => 15, // SIGTERM
85+
);
7886

7987
/**
8088
* Exit codes translation table.
@@ -169,16 +177,7 @@ public function __construct($commandline, $cwd = null, array $env = null, $input
169177

170178
public function __destruct()
171179
{
172-
if ($this->isRunning()) {
173-
$this->doSignal(15, false);
174-
usleep(10000);
175-
}
176-
if ($this->isRunning()) {
177-
usleep(100000);
178-
$this->doSignal(9, false);
179-
}
180-
181-
// Don't call ->stop() nor ->close() since we don't want to wait for the subprocess here
180+
$this->stop(0);
182181
}
183182

184183
public function __clone()
@@ -227,7 +226,7 @@ public function run($callback = null)
227226
*/
228227
public function mustRun($callback = null)
229228
{
230-
if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
229+
if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
231230
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
232231
}
233232

@@ -388,17 +387,9 @@ public function wait($callback = null)
388387
* Returns the Pid (process identifier), if applicable.
389388
*
390389
* @return int|null The process id if running, null otherwise
391-
*
392-
* @throws RuntimeException In case --enable-sigchild is activated
393390
*/
394391
public function getPid()
395392
{
396-
if ($this->isSigchildEnabled()) {
397-
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process identifier can not be retrieved.');
398-
}
399-
400-
$this->updateStatus(false);
401-
402393
return $this->isRunning() ? $this->processInformation['pid'] : null;
403394
}
404395

@@ -410,7 +401,7 @@ public function getPid()
410401
* @return Process
411402
*
412403
* @throws LogicException In case the process is not running
413-
* @throws RuntimeException In case --enable-sigchild is activated
404+
* @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
414405
* @throws RuntimeException In case of failure
415406
*/
416407
public function signal($signal)
@@ -604,7 +595,9 @@ public function clearErrorOutput()
604595
*/
605596
public function getExitCode()
606597
{
607-
if ($this->isSigchildEnabled() && !$this->enhanceSigchildCompatibility) {
598+
if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
599+
$this->stop(0);
600+
608601
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
609602
}
610603

@@ -621,8 +614,6 @@ public function getExitCode()
621614
*
622615
* @return null|string A string representation for the exit status code, null if the Process is not terminated.
623616
*
624-
* @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled
625-
*
626617
* @see http://tldp.org/LDP/abs/html/exitcodes.html
627618
* @see http://en.wikipedia.org/wiki/Unix_signal
628619
*/
@@ -659,12 +650,12 @@ public function hasBeenSignaled()
659650
{
660651
$this->requireProcessIsTerminated(__FUNCTION__);
661652

662-
if ($this->isSigchildEnabled()) {
653+
if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
654+
$this->stop(0);
655+
663656
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
664657
}
665658

666-
$this->updateStatus(false);
667-
668659
return $this->processInformation['signaled'];
669660
}
670661

@@ -682,12 +673,12 @@ public function getTermSignal()
682673
{
683674
$this->requireProcessIsTerminated(__FUNCTION__);
684675

685-
if ($this->isSigchildEnabled()) {
676+
if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
677+
$this->stop(0);
678+
686679
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
687680
}
688681

689-
$this->updateStatus(false);
690-
691682
return $this->processInformation['termsig'];
692683
}
693684

@@ -704,8 +695,6 @@ public function hasBeenStopped()
704695
{
705696
$this->requireProcessIsTerminated(__FUNCTION__);
706697

707-
$this->updateStatus(false);
708-
709698
return $this->processInformation['stopped'];
710699
}
711700

@@ -722,8 +711,6 @@ public function getStopSignal()
722711
{
723712
$this->requireProcessIsTerminated(__FUNCTION__);
724713

725-
$this->updateStatus(false);
726-
727714
return $this->processInformation['stopsig'];
728715
}
729716

@@ -797,7 +784,7 @@ public function stop($timeout = 10, $signal = null)
797784
usleep(1000);
798785
} while ($this->isRunning() && microtime(true) < $timeoutMicro);
799786

800-
if ($this->isRunning() && !$this->isSigchildEnabled()) {
787+
if ($this->isRunning()) {
801788
// Avoid exception here: process is supposed to be running, but it might have stopped just
802789
// after this line. In any case, let's silently discard the error, we cannot do anything.
803790
$this->doSignal($signal ?: 9, false);
@@ -1262,9 +1249,15 @@ private function getDescriptors()
12621249

12631250
if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
12641251
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
1265-
$descriptors = array_merge($descriptors, array(array('pipe', 'w')));
1252+
$descriptors[3] = array('pipe', 'w');
1253+
1254+
$trap = '';
1255+
foreach (self::$posixSignals as $s) {
1256+
$trap .= "trap 'echo s$s >&3' $s;";
1257+
}
12661258

1267-
$this->commandline = '('.$this->commandline.') 3>/dev/null; code=$?; echo $code >&3; exit $code';
1259+
$this->commandline = $trap.'{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
1260+
$this->commandline .= 'pid=$!; echo p$pid >&3; wait $pid; code=$?; echo x$code >&3; exit $code';
12681261
}
12691262

12701263
return $descriptors;
@@ -1311,10 +1304,13 @@ protected function updateStatus($blocking)
13111304
}
13121305

13131306
$this->processInformation = proc_get_status($this->process);
1314-
$this->captureExitCode();
13151307

13161308
$this->readPipes($blocking, '\\' === DIRECTORY_SEPARATOR ? !$this->processInformation['running'] : true);
13171309

1310+
if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
1311+
$this->processInformation = $this->fallbackStatus + $this->processInformation;
1312+
}
1313+
13181314
if (!$this->processInformation['running']) {
13191315
$this->close();
13201316
}
@@ -1331,7 +1327,7 @@ protected function isSigchildEnabled()
13311327
return self::$sigchild;
13321328
}
13331329

1334-
if (!function_exists('phpinfo')) {
1330+
if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
13351331
return self::$sigchild = false;
13361332
}
13371333

@@ -1375,24 +1371,24 @@ private function readPipes($blocking, $close)
13751371

13761372
$callback = $this->callback;
13771373
foreach ($result as $type => $data) {
1378-
if (3 == $type) {
1379-
$this->fallbackExitcode = (int) $data;
1374+
if (3 === $type) {
1375+
foreach (explode("\n", substr($data, 0, -1)) as $data) {
1376+
if ('p' === $data[0]) {
1377+
$this->fallbackStatus['pid'] = (int) substr($data, 1);
1378+
} elseif ('s' === $data[0]) {
1379+
$this->fallbackStatus['signaled'] = true;
1380+
$this->fallbackStatus['exitcode'] = -1;
1381+
$this->fallbackStatus['termsig'] = (int) substr($data, 1);
1382+
} elseif ('x' === $data[0] && !isset($this->fallbackStatus['signaled'])) {
1383+
$this->fallbackStatus['exitcode'] = (int) substr($data, 1);
1384+
}
1385+
}
13801386
} else {
13811387
$callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
13821388
}
13831389
}
13841390
}
13851391

1386-
/**
1387-
* Captures the exitcode if mentioned in the process information.
1388-
*/
1389-
private function captureExitCode()
1390-
{
1391-
if (isset($this->processInformation['exitcode']) && -1 != $this->processInformation['exitcode']) {
1392-
$this->exitcode = $this->processInformation['exitcode'];
1393-
}
1394-
}
1395-
13961392
/**
13971393
* Closes process resource, closes file handles, sets the exitcode.
13981394
*
@@ -1402,19 +1398,19 @@ private function close()
14021398
{
14031399
$this->processPipes->close();
14041400
if (is_resource($this->process)) {
1405-
$exitcode = proc_close($this->process);
1406-
} else {
1407-
$exitcode = -1;
1401+
proc_close($this->process);
14081402
}
1409-
1410-
$this->exitcode = -1 !== $exitcode ? $exitcode : (null !== $this->exitcode ? $this->exitcode : -1);
1403+
$this->exitcode = $this->processInformation['exitcode'];
14111404
$this->status = self::STATUS_TERMINATED;
14121405

1413-
if (-1 === $this->exitcode && null !== $this->fallbackExitcode) {
1414-
$this->exitcode = $this->fallbackExitcode;
1415-
} elseif (-1 === $this->exitcode && $this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
1416-
// if process has been signaled, no exitcode but a valid termsig, apply Unix convention
1417-
$this->exitcode = 128 + $this->processInformation['termsig'];
1406+
if (-1 === $this->exitcode) {
1407+
if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
1408+
// if process has been signaled, no exitcode but a valid termsig, apply Unix convention
1409+
$this->exitcode = 128 + $this->processInformation['termsig'];
1410+
} elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
1411+
$this->processInformation['signaled'] = true;
1412+
$this->processInformation['termsig'] = -1;
1413+
}
14181414
}
14191415

14201416
// Free memory from self-reference callback created by buildCallback
@@ -1433,7 +1429,7 @@ private function resetProcessData()
14331429
$this->starttime = null;
14341430
$this->callback = null;
14351431
$this->exitcode = null;
1436-
$this->fallbackExitcode = null;
1432+
$this->fallbackStatus = array();
14371433
$this->processInformation = null;
14381434
$this->stdout = null;
14391435
$this->stderr = null;
@@ -1453,7 +1449,7 @@ private function resetProcessData()
14531449
* @return bool True if the signal was sent successfully, false otherwise
14541450
*
14551451
* @throws LogicException In case the process is not running
1456-
* @throws RuntimeException In case --enable-sigchild is activated
1452+
* @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
14571453
* @throws RuntimeException In case of failure
14581454
*/
14591455
private function doSignal($signal, $throwException)
@@ -1466,9 +1462,9 @@ private function doSignal($signal, $throwException)
14661462
return false;
14671463
}
14681464

1469-
if ($this->isSigchildEnabled()) {
1465+
if ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled() && !isset(self::$posixSignals[$signal]) && !(function_exists('posix_kill') && @posix_kill($this->getPid(), $signal))) {
14701466
if ($throwException) {
1471-
throw new RuntimeException('This PHP has been compiled with --enable-sigchild. The process can not be signaled.');
1467+
throw new RuntimeException('This PHP has been compiled with --enable-sigchild and posix_kill() is not available.');
14721468
}
14731469

14741470
return false;
@@ -1493,7 +1489,10 @@ private function doSignal($signal, $throwException)
14931489
return false;
14941490
}
14951491

1496-
$this->latestSignal = $signal;
1492+
$this->latestSignal = (int) $signal;
1493+
$this->fallbackStatus['signaled'] = true;
1494+
$this->fallbackStatus['exitcode'] = -1;
1495+
$this->fallbackStatus['termsig'] = $this->latestSignal;
14971496

14981497
return true;
14991498
}

src/Symfony/Component/Process/Tests/PhpProcessTest.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,20 @@ public function testNonBlockingWorks()
3030

3131
public function testCommandLine()
3232
{
33-
if ('phpdbg' === PHP_SAPI) {
34-
$this->markTestSkipped('phpdbg SAPI is not supported by this test.');
35-
}
36-
3733
$process = new PhpProcess(<<<PHP
3834
<?php echo 'foobar';
3935
PHP
4036
);
4137

42-
$f = new PhpExecutableFinder();
43-
$commandLine = $f->find();
38+
$commandLine = $process->getCommandLine();
4439

45-
$this->assertSame($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP before start');
40+
$f = new PhpExecutableFinder();
41+
$this->assertContains($f->find(), $commandLine, '::getCommandLine() returns the command line of PHP before start');
4642

4743
$process->start();
48-
$this->assertSame($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after start');
44+
$this->assertContains($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after start');
4945

5046
$process->wait();
51-
$this->assertSame($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after wait');
47+
$this->assertContains($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after wait');
5248
}
5349
}

0 commit comments

Comments
 (0)