Skip to content

Commit 0f982e6

Browse files
[Process] Make tests more deterministic
1 parent 6a92f4e commit 0f982e6

File tree

4 files changed

+181
-187
lines changed

4 files changed

+181
-187
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ before_install:
4949

5050
install:
5151
- if [[ $deps != skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi;
52+
- COMPONENTS=src/Symfony/Component/Process
5253
- if [[ $deps != skip && $deps ]]; then php .travis.php $TRAVIS_COMMIT_RANGE $TRAVIS_BRANCH $COMPONENTS; fi;
5354
- if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then SYMFONY_VERSION=$(git branch -r | grep -o '/[1-9].*' | tail -n 1 | sed s/.//); else SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*'); fi;
5455
- if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; fi;

src/Symfony/Component/Process/Process.php

+40-42
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,12 @@ class Process
7676

7777
private static $sigchild;
7878
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
79+
1, // SIGHUP
80+
2, // SIGINT
81+
3, // SIGQUIT
82+
6, // SIGABRT
83+
14, // SIGALRM
84+
15, // SIGTERM
8585
);
8686

8787
/**
@@ -285,27 +285,34 @@ public function start($callback = null)
285285
if (!isset($this->options['bypass_shell'])) {
286286
$this->options['bypass_shell'] = true;
287287
}
288-
}
288+
} elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
289+
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
290+
$descriptors[3] = array('pipe', 'w');
291+
292+
$commandline = '';
293+
foreach (self::$posixSignals as $s) {
294+
$commandline .= "trap 'echo s$s >&3' $s;";
295+
}
289296

290-
$ptsWorkaround = null;
297+
$commandline .= '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
298+
$commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo x$code >&3; exit $code';
291299

292-
if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
293300
// Workaround for the bug, when PTS functionality is enabled.
294301
// @see : https://bugs.php.net/69442
295302
$ptsWorkaround = fopen(__FILE__, 'r');
296303
}
297304

298305
$this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
299306

300-
if ($ptsWorkaround) {
301-
fclose($ptsWorkaround);
302-
}
303-
304307
if (!is_resource($this->process)) {
305308
throw new RuntimeException('Unable to launch a new process.');
306309
}
307310
$this->status = self::STATUS_STARTED;
308311

312+
if (isset($descriptors[3])) {
313+
fclose($ptsWorkaround);
314+
$this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
315+
}
309316
if ($this->tty) {
310317
return;
311318
}
@@ -422,6 +429,8 @@ public function signal($signal)
422429
public function disableOutput()
423430
{
424431
if ($this->isRunning()) {
432+
$this->stop(0);
433+
425434
throw new RuntimeException('Disabling output while the process is running is not possible.');
426435
}
427436
if (null !== $this->idleTimeout) {
@@ -443,6 +452,8 @@ public function disableOutput()
443452
public function enableOutput()
444453
{
445454
if ($this->isRunning()) {
455+
$this->stop(0);
456+
446457
throw new RuntimeException('Enabling output while the process is running is not possible.');
447458
}
448459

@@ -472,6 +483,8 @@ public function isOutputDisabled()
472483
public function getOutput()
473484
{
474485
if ($this->outputDisabled) {
486+
$this->stop(0);
487+
475488
throw new LogicException('Output has been disabled.');
476489
}
477490

@@ -1245,22 +1258,8 @@ private function getDescriptors()
12451258
} else {
12461259
$this->processPipes = UnixPipes::create($this, $this->input);
12471260
}
1248-
$descriptors = $this->processPipes->getDescriptors($this->outputDisabled);
1249-
1250-
if (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
1251-
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
1252-
$descriptors[3] = array('pipe', 'w');
1253-
1254-
$trap = '';
1255-
foreach (self::$posixSignals as $s) {
1256-
$trap .= "trap 'echo s$s >&3' $s;";
1257-
}
1258-
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';
1261-
}
12621261

1263-
return $descriptors;
1262+
return $this->processPipes->getDescriptors($this->outputDisabled);
12641263
}
12651264

12661265
/**
@@ -1462,14 +1461,6 @@ private function doSignal($signal, $throwException)
14621461
return false;
14631462
}
14641463

1465-
if ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled() && !isset(self::$posixSignals[$signal]) && !(function_exists('posix_kill') && @posix_kill($this->getPid(), $signal))) {
1466-
if ($throwException) {
1467-
throw new RuntimeException('This PHP has been compiled with --enable-sigchild and posix_kill() is not available.');
1468-
}
1469-
1470-
return false;
1471-
}
1472-
14731464
if ('\\' === DIRECTORY_SEPARATOR) {
14741465
exec(sprintf('taskkill /F /T /PID %d 2>&1', $this->getPid()), $output, $exitCode);
14751466
if ($exitCode && $this->isRunning()) {
@@ -1479,14 +1470,21 @@ private function doSignal($signal, $throwException)
14791470

14801471
return false;
14811472
}
1482-
}
1483-
1484-
if (true !== @proc_terminate($this->process, $signal) && '\\' !== DIRECTORY_SEPARATOR) {
1485-
if ($throwException) {
1486-
throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
1473+
} else {
1474+
if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
1475+
$ok = @proc_terminate($this->process, $signal);
1476+
} elseif (function_exists('posix_kill')) {
1477+
$ok = @posix_kill($this->getPid(), $signal);
1478+
} elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $this->getPid()), array(2 => array('pipe', 'w')), $pipes)) {
1479+
$ok = false === fgets($pipes[2]);
14871480
}
1481+
if (!$ok) {
1482+
if ($throwException) {
1483+
throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
1484+
}
14881485

1489-
return false;
1486+
return false;
1487+
}
14901488
}
14911489

14921490
$this->latestSignal = (int) $signal;

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,18 @@ function handleSignal($signal)
3030
break;
3131
}
3232

33-
echo "received signal $name\n";
33+
echo "signal $name\n";
3434
}
3535

36-
declare (ticks = 1);
3736
pcntl_signal(SIGTERM, 'handleSignal');
3837
pcntl_signal(SIGINT, 'handleSignal');
3938

39+
echo 'received ';
40+
4041
$duration = isset($argv[1]) ? (int) $argv[1] : 3;
4142
$start = microtime(true);
4243

4344
while ($duration > (microtime(true) - $start)) {
44-
usleep(1000);
45+
usleep(10000);
46+
pcntl_signal_dispatch();
4547
}

0 commit comments

Comments
 (0)