mirror of
https://github.com/symfony/process.git
synced 2026-03-23 23:42:06 +01:00
Merge branch '7.4' into 8.0
* 7.4: [JsonPath] Use composer packages for JsonPath compliance test suite Fix negative delays with AMQP messenger transport [TwigBundle] Align TemplateIterator handling of @! original bundle templates with TwigExtension [AssetMapper] Batch concurrent requests to prevent flooding jsdelivr [HttpFoundation][Cache] Fix VARBINARY columns on sqlsrv [Cache] Fix calling the callback wrapper for ChainAdapter [Routing] Fix simple parameter mappings in routes [Process] Fix dealing with broken stdin pipes
This commit is contained in:
@@ -135,9 +135,11 @@ abstract class AbstractPipes implements PipesInterface
|
||||
|
||||
foreach ($w as $stdin) {
|
||||
if (isset($this->inputBuffer[0])) {
|
||||
$written = fwrite($stdin, $this->inputBuffer);
|
||||
if (false === $written = @fwrite($stdin, $this->inputBuffer)) {
|
||||
return $this->closeBrokenInputPipe();
|
||||
}
|
||||
$this->inputBuffer = substr($this->inputBuffer, $written);
|
||||
if (isset($this->inputBuffer[0])) {
|
||||
if (isset($this->inputBuffer[0]) && isset($this->pipes[0])) {
|
||||
return [$this->pipes[0]];
|
||||
}
|
||||
}
|
||||
@@ -148,12 +150,14 @@ abstract class AbstractPipes implements PipesInterface
|
||||
if (!isset($data[0])) {
|
||||
break;
|
||||
}
|
||||
$written = fwrite($stdin, $data);
|
||||
if (false === $written = @fwrite($stdin, $data)) {
|
||||
return $this->closeBrokenInputPipe();
|
||||
}
|
||||
$data = substr($data, $written);
|
||||
if (isset($data[0])) {
|
||||
$this->inputBuffer = $data;
|
||||
|
||||
return [$this->pipes[0]];
|
||||
return isset($this->pipes[0]) ? [$this->pipes[0]] : null;
|
||||
}
|
||||
}
|
||||
if (feof($input)) {
|
||||
@@ -178,6 +182,18 @@ abstract class AbstractPipes implements PipesInterface
|
||||
return null;
|
||||
}
|
||||
|
||||
private function closeBrokenInputPipe(): void
|
||||
{
|
||||
$this->lastError = error_get_last()['message'] ?? null;
|
||||
if (\is_resource($this->pipes[0] ?? null)) {
|
||||
fclose($this->pipes[0]);
|
||||
}
|
||||
unset($this->pipes[0]);
|
||||
|
||||
$this->input = null;
|
||||
$this->inputBuffer = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
||||
@@ -676,6 +676,24 @@ class ProcessTest extends TestCase
|
||||
$this->assertFalse($process->isRunning());
|
||||
}
|
||||
|
||||
public function testStopDoesNotThrowAfterBrokenPipe()
|
||||
{
|
||||
if ('\\' === \DIRECTORY_SEPARATOR) {
|
||||
$this->markTestSkipped('Broken pipe notices are specific to Unix-like platforms.');
|
||||
}
|
||||
|
||||
$process = $this->getProcess([self::$phpBin, '-r', 'exit(0);'], null, null, str_repeat('*', PipesInterface::CHUNK_SIZE * 32));
|
||||
|
||||
$process->run();
|
||||
$this->assertSame(0, $process->getExitCode());
|
||||
|
||||
$process->stop(0);
|
||||
|
||||
// __destruct() should not trigger a broken pipe notice
|
||||
self::$process = $process = null;
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
public function testIsSuccessful()
|
||||
{
|
||||
$process = $this->getProcess('echo foo');
|
||||
|
||||
Reference in New Issue
Block a user