Description
Symfony version(s) affected: 5.2.0
Description
I would like to call an interactive application using the symfony process component without relying on any non-cross-platform functionality such as the allocation of a tty.
The support for this is indicated in the docs as "Using PHP Streams as the Standard Input of a Process": https://symfony.com/doc/current/components/process.html#using-php-streams-as-the-standard-input-of-a-process
(Originally implemented here: #18386)
Now when trying this using the code below, multiple problems arise:
- Using
bash
on linux:- The shell prompt is not shown
- Output of programs (e.g.
nano
) with complex CLI-renderings (e.g. usingncurses
) is partially broken but can be interacted with using the standard input just fine. - The process instance does not seem to realize when closing the executed bash by writing
exit
. The process does not stop but any subsequent input produces an infinite loop with:
PHP Notice: fwrite(): write of 5 bytes failed with errno=32 Broken pipe in .../vendor/symfony/process/Pipes/AbstractPipes. PHP on line 128 PHP Stack trace: PHP 1. {main}() .../test.php:0 PHP 2. Symfony\Component\Process\Process->mustRun() .../test.php:15 PHP 3. Symfony\Component\Process\Process->run() .../vendor/symfony/process/Process.php:256 PHP 4. Symfony\Component\Process\Process->wait() .../vendor/symfony/process/Process.php:239 PHP 5. Symfony\Component\Process\Process->readPipes() .../vendor/symfony/process/Process.php:417 PHP 6. Symfony\Component\Process\Pipes\UnixPipes->readAndWrite() .../vendor/symfony/process/Process.php:1424 PHP 7. Symfony\Component\Process\Pipes\UnixPipes->write() .../vendor/symfony/process/Pipes/UnixPipes.php:95 PHP 8. fwrite() .../vendor/symfony/process/Pipes/AbstractPipes.php:128 PHP Notice: fwrite(): write of 5 bytes failed with errno=32 Broken pipe in .../vendor/symfony/process/Pipes/AbstractPipes. PHP on line 128 ...
- Using
git-bash
on Windows 10:- Interactive input seems to get ignored altogether yielding no (visible) output on any input
How to reproduce
<?php
require_once __DIR__ . '/vendor/autoload.php';
$process = new \Symfony\Component\Process\Process(['bash']);
$process->setInput(STDIN);
$process->mustRun(function(string $type, string $buffer) {
switch ($type)
{
case 'err': fputs(STDERR, $buffer); break;
case 'out': fputs(STDOUT, $buffer); break;
default: throw new LogicException("Unknown output type: {$type}");
}
});
Possible Solution
I don't have a possible solution for the symfony component but the desired behaviour can be achieved with plain php like this:
<?php
proc_close(proc_open('bash', [STDIN, STDOUT, STDOUT], $_));
Additional context
Related issues have been discussed here: