Skip to content

[Process] Passing standard IO streams to executed process AKA calling an interactive application with cross-platform support #39482

Closed
@arnegroskurth

Description

@arnegroskurth

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. using ncurses) 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:

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions