Skip to content
Permalink
Browse files

bug #25417 [Process] Dont rely on putenv(), it fails on ZTS PHP (nico…

…las-grekas)

This PR was merged into the 3.3 branch.

Discussion
----------

[Process] Dont rely on putenv(), it fails on ZTS PHP

| Q             | A
| ------------- | ---
| Branch?       | 3.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #24924
| License       | MIT
| Doc PR        | -

`putenv()` is not thread safe, but ZTS is PHP defaults on Windows.

Commits
-------

ef632ec [Process] Dont rely on putenv(), it fails on ZTS PHP
  • Loading branch information...
fabpot committed Dec 11, 2017
2 parents f744236 + ef632ec commit 9fda6af7a25136d7618c1956ed7055a5a79b1221
@@ -343,6 +343,7 @@ protected function doRequestInProcess($request)
{
$deprecationsFile = tempnam(sys_get_temp_dir(), 'deprec');
putenv('SYMFONY_DEPRECATIONS_SERIALIZE='.$deprecationsFile);
$_ENV['SYMFONY_DEPRECATIONS_SERIALIZE'] = $deprecationsFile;
$process = new PhpProcess($this->getScript($request), null, null);
$process->run();
@@ -304,19 +304,16 @@ public function start(callable $callback = null/*, array $env = array()*/)
$inheritEnv = true;
}
$envBackup = array();
if (null !== $env && $inheritEnv) {
foreach ($env as $k => $v) {
$envBackup[$k] = getenv($k);
putenv(false === $v || null === $v ? $k : "$k=$v");
}
$env = null;
$env += $this->getDefaultEnv();
} elseif (null !== $env) {
@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);
} else {
$env = $this->getDefaultEnv();
}
if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
$this->options['bypass_shell'] = true;
$commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env);
$commandline = $this->prepareWindowsCommandLine($commandline, $env);
} elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild
$descriptors[3] = array('pipe', 'w');
@@ -332,10 +329,6 @@ public function start(callable $callback = null/*, array $env = array()*/)
$this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $this->options);
foreach ($envBackup as $k => $v) {
putenv(false === $v ? $k : "$k=$v");
}
if (!is_resource($this->process)) {
throw new RuntimeException('Unable to launch a new process.');
}
@@ -1623,7 +1616,7 @@ private function doSignal($signal, $throwException)
return true;
}
private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env = null)
private function prepareWindowsCommandLine($cmd, array &$env)
{
$uid = uniqid('', true);
$varCount = 0;
@@ -1636,7 +1629,7 @@ private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env
[^"%!^]*+
)++
) | [^"]*+ )"/x',
function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) {
function ($m) use (&$env, &$varCache, &$varCount, $uid) {
if (!isset($m[1])) {
return $m[0];
}
@@ -1654,13 +1647,7 @@ function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) {
$value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"';
$var = $uid.++$varCount;
if (null === $env) {
putenv("$var=$value");
} else {
$env[$var] = $value;
}
$envBackup[$var] = false;
$env[$var] = $value;
return $varCache[$m[0]] = '!'.$var.'!';
},
@@ -1728,4 +1715,27 @@ private function escapeArgument($argument)
return '"'.str_replace(array('"', '^', '%', '!', "\n"), array('""', '"^^"', '"^%"', '"^!"', '!LF!'), $argument).'"';
}
private function getDefaultEnv()
{
if (\PHP_VERSION_ID >= 70100) {
$env = getenv();
} else {
$env = array();
foreach ($_SERVER as $k => $v) {
if (is_string($v) && false !== $v = getenv($k)) {
$env[$k] = $v;
}
}
}
foreach ($_ENV as $k => $v) {
if (is_string($v)) {
$env[$k] = $v;
}
}
return $env;
}
}
@@ -1406,6 +1406,7 @@ public function testSetBadEnv()
public function testEnvBackupDoesNotDeleteExistingVars()
{
putenv('existing_var=foo');
$_ENV['existing_var'] = 'foo';
$process = $this->getProcess('php -r "echo getenv(\'new_test_var\');"');
$process->setEnv(array('existing_var' => 'bar', 'new_test_var' => 'foo'));
$process->inheritEnvironmentVariables();
@@ -1415,20 +1416,27 @@ public function testEnvBackupDoesNotDeleteExistingVars()
$this->assertSame('foo', $process->getOutput());
$this->assertSame('foo', getenv('existing_var'));
$this->assertFalse(getenv('new_test_var'));
putenv('existing_var');
unset($_ENV['existing_var']);
}
public function testEnvIsInherited()
{
$process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ'));
putenv('FOO=BAR');
$_ENV['FOO'] = 'BAR';
$process->run();
$expected = array('BAR' => 'BAZ', 'FOO' => 'BAR');
$env = array_intersect_key(unserialize($process->getOutput()), $expected);
$this->assertEquals($expected, $env);
putenv('FOO');
unset($_ENV['FOO']);
}
/**
@@ -1439,6 +1447,7 @@ public function testInheritEnvDisabled()
$process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ'));
putenv('FOO=BAR');
$_ENV['FOO'] = 'BAR';
$this->assertSame($process, $process->inheritEnvironmentVariables(false));
$this->assertFalse($process->areEnvironmentVariablesInherited());
@@ -1450,6 +1459,9 @@ public function testInheritEnvDisabled()
unset($expected['FOO']);
$this->assertSame($expected, $env);
putenv('FOO');
unset($_ENV['FOO']);
}
public function testGetCommandLine()

0 comments on commit 9fda6af

Please sign in to comment.
You can’t perform that action at this time.